BZOJ4870: [Shoi2017]组合数问题

xiaoxiao2021-02-28  170

BZOJ4870

。。估计大多数人都是看题推式子。。然后各种码逆元。。 CRT 。。 Lucas 定理等奇奇怪怪的东西。。然后还发现拿不了满分。。

最后看到题解,就各种憋住的**破口而出。。 其实题目就是求 nk 个数中,取得的数模 k r的方案数。。 显然有 fi,j=fi1,j1+fi1,j ( fi,0=fi1,0+fi1,k1 ) 这,这 TM 矩阵乘法优化一下不就好了!!?

【代码】

#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <bitset> #define N 100005 #define mod 1000000007 #define INF 0x7fffffff using namespace std; typedef long long ll; ll read() { ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } int n,Mod,k,r; class Matrix{ public: int v[55][55]; int x,y; }a,b; Matrix operator *(Matrix A,Matrix B){ Matrix rtn;rtn.x=A.x,rtn.y=B.y; for(int i=1;i<=A.x;i++) for(int j=1;j<=B.y;j++) { rtn.v[i][j]=0; for(int k=1;k<=A.y;k++) rtn.v[i][j]=(rtn.v[i][j]+1LL*A.v[i][k]*B.v[k][j]%Mod)%Mod; } return rtn; } Matrix Qpow(Matrix X,ll Y) { Matrix rtn;rtn.x=rtn.y=k; for(int i=1;i<=k;i++) for(int j=1;j<=k;j++) rtn.v[i][j]=(i==j)?1:0; while(Y) { if(Y&1) rtn=rtn*X; X=X*X;Y>>=1; } return rtn; } int Ksm(int x,ll y){ int rtn=1; while(y) { if(y&1) rtn=1LL*x*rtn%Mod; x=1LL*x*x%Mod;y>>=1; } return rtn; } int main() { n=read(),Mod=read(),k=read(),r=read(); if(k==1) { printf("%d\n",Ksm(2,n)); return 0; } a.v[1][1]=1;a.x=1,a.y=b.x=b.y=k; for(int i=1;i<=k;i++) { b.v[i][i]=1; if(i!=1) b.v[i][i-1]=1; else b.v[i][k]=1; } b=Qpow(b,1LL*n*k); a=a*b; printf("%d\n",a.v[1][r+1]); return 0; }
转载请注明原文地址: https://www.6miu.com/read-21004.html

最新回复(0)