T1:礼物
想错方向了,实际上很简单。
我想的是:显然题目求的是$\sum_{i=1}^{n} i^{k}2^{i}$,然后或许可以通过化式子变成与n无关的复杂度?
然后就不停往斯特林数反演和下降幂的方向想,最后什么都没想出来。
其实想一会就应该意识到:这完全就是一个不可直接化简的式子啊。
$A[i]$表示第$i$个人送的礼物数,$S[i]$为前缀和,那么显然有$S[i]=2*S[i-1]+i^k$,这样就把思路引导矩乘方面去了。
如何矩乘呢?考虑题目的提示。首先$i^k$这个东西不好直接转移到$(i+1)^k$,其次发现转移的话根据二项式定理需要$i^1,i^2,...,i^k$的所有数,最后从题目“$K \leq 10$”可以猜到,一定是将$i^1 i^2 ... i^k$全部扔进矩阵,和$S[i]$一起转移,转移矩阵则正好是$C_i^j$的转置矩阵,这样就可以$O(\log n \times k^3)$解决问题
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define rep(i,l,r) for (int i=l; i<=r; i++) 5 typedef long long ll; 6 using namespace std; 7 8 const ll P=1000000007; 9 ll n,c[20][20]; 10 int m; 11 12 struct M{ ll a[20][20]; M(){ memset(a,0,sizeof(a)); } }tr,a1,a2; 13 M mul(M a,M b){ 14 M c; 15 rep(i,0,m+1) rep(j,0,m+1) rep(k,0,m+1) c.a[i][k]=(c.a[i][k]+a.a[i][j]*b.a[j][k])%P; 16 return c; 17 } 18 19 M ksm(M a,ll b){ 20 M x=tr; 21 for (; b; x=mul(x,x),b>>=1) 22 if (b & 1) a=mul(a,x); 23 return a; 24 } 25 26 int main(){ 27 scanf("%lld%d",&n,&m); 28 rep(i,0,m) c[i][0]=1; 29 rep(i,1,m) rep(j,1,i) c[i][j]=(c[i-1][j-1]+c[i-1][j])%P; 30 rep(i,0,m){ 31 a1.a[0][i]=a2.a[0][i]=1; 32 rep(j,0,i) tr.a[j][i]=c[i][j]; 33 } 34 tr.a[m+1][m+1]=2; tr.a[m][m+1]=1; 35 a1=ksm(a1,n-1); a2=ksm(a2,n); 36 printf("%lld\n",(a2.a[0][m+1]-a1.a[0][m+1]+P)%P); 37 return 0; 38 }