bzoj3157 国王奇遇记 && bzoj 3516 国王奇遇记加强版
求∑i(i>0&&i<=n) im*mi mod 1000000007
令fk=∑i(i>0&&i<=n) ik*mi
两边同乘(m-1),整理得:(m-1)fk=nk*mn+1+∑i(i>0&&i<=n) mi*[(i-1)k-ik]
用二项式定理展开(i-1)k,整理得:(m-1)fk=nk*mn+1+∑i(i>0&&i<=n)mi*∑j(j>=0&&j<k)C(k,j)*(-1)k-j*ij
交换一下两个循环的位置,整理得(m-1)fk=nk*mn+1+∑j(j>=0&&j<k)C(k,j)*(-1)k-j*∑i(i>0&&i<=n)ij*mi
好像发现了什么熟悉的东西。。。
(m-1)fk=nk*mn+1+∑j(j>=0&&j<k)C(k,j)*(-1)k-j*fj
这样就能O(m2)计算了
这两题做法一模一样。。。我就贴个3157的代码吧
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int MAXN=205; const int Mod=1e9+7; typedef long long ll; int n,m; inline ll qpow(ll x,int k){ ll ans=1; for(;k;x=x*x%Mod,k>>=1) if(k&1)ans=ans*x%Mod; return ans; } int C[MAXN][MAXN]; inline void Init(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ C[i][0]=C[i][i]=1; for(int j=1;j<i;++j){ C[i][j]=(C[i-1][j]+C[i-1][j-1])%Mod; } } } int ans,s[MAXN]; inline void Solve(){ int inv=qpow(m-1,Mod-2); int nn=1,mm=qpow(m,n+1); s[0]=(qpow(m,n+1)-m+Mod)*inv%Mod; for(int i=1;i<=m;++i){ nn=(ll)nn*n%Mod; s[i]=(ll)nn*mm%Mod; for(int j=0;j<i;++j){ int res=(ll)C[i][i-j]*s[j]%Mod; if((i-j)&1)s[i]=(s[i]+Mod-res)%Mod; else s[i]=(s[i]+res)%Mod; } s[i]=(ll)s[i]*inv%Mod; } printf("%d\n",s[m]); } int main(){ Init(); if(m==1){ ans=((ll)n*(n+1)>>1)%Mod; printf("%d\n",ans); } else Solve(); return 0; }
其实还有个再加强版。。。太神,不会做