一如既往的垃圾,又回到了那个场场垫底的自己,明明考场上都想到正解了,但是就是拿不到分,可能是互奶把rp用光了吧以后一定加强训练代码能力。
T1:
考场上一直yy矩阵快速幂,虽然自己矩阵快速幂一点都不会还是硬着头皮yy,发现不可做之后并没有及时转化思路,但其实自己预处理的数组就是正解。
切记:不仅矩阵快速幂是log的,普通快速幂也是2333
然后这题其实很水啊,我们设$dp[i][j]$为前$i$列放$j$个棋子的方案数,然后枚举最后一列放多少个棋子就好了。
转移方程为$dp[i][j]=\sum{dp[i-1][j-k]*C_n^k}$,这样转移m列显然不行,考虑性质,第$i$列和第$i+kn$列的摆放方式一定相同,所以后面的组合数乘还有多少这样的列就好了即${C_n^k}^{\frac{m-i}{n}+1}$,但这样的复杂度是$O(n^4logn)$的,发现组合数可以预处理,于是去掉了log
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10,mod=1e9+7; 4 #define int long long 5 int n,m,c,fac[N],inv[N]; 6 int f[105][105*105],pre[105][105*105]; 7 int min(int a,int b){ 8 return a<b?a:b; 9 } 10 int qpow(int a,int b){ 11 int ans=1; 12 while(b){ 13 if(b&1) ans=ans*a%mod; 14 b>>=1; 15 a=a*a%mod; 16 } 17 return ans%mod; 18 } 19 int C(int a,int b){ 20 return fac[a]*inv[b]%mod*inv[a-b]%mod; 21 } 22 signed main(){ 23 fac[0]=1; 24 for(int i=1;i<=10001;++i) fac[i]=fac[i-1]*i%mod; 25 inv[10001]=qpow(fac[10001],mod-2); 26 for(int i=10001;i;--i) inv[i-1]=inv[i]*i%mod; 27 scanf("%lld%lld%lld",&n,&m,&c); 28 f[0][0]=1; 29 for(int i=0;i<=n;++i) for(int j=0;j<=max(n,c);++j) pre[i][j]=qpow(C(n,j),(m-i)/n+1)%mod; 30 // for(int i=1;i<=n;++i,cout<<endl) for(int j=1;j<=n;++j) cout<<pre[i][j]; 31 for(int i=1;i<=n;++i){ 32 for(int j=0;j<=c;++j){ 33 for(int k=0;k<=min(n,j);++k){ 34 (f[i][j]+=f[i-1][j-k]*pre[i][k]%mod)%=mod; 35 // cout<<pre[i][k]<<" "<<qpow(C(n,k),(m-i)/n+1)<<endl; 36 } 37 } 38 } 39 printf("%lld",f[n][c]%mod); 40 } 41 /* 42 2 3 1 43 */