bzoj 3612: [Heoi2014]平衡【整數劃分dp】
阿新 • • 發佈:2018-09-13
情況 技術分享 個數 ++ const pre 全部 mage print
其實就是-n~n中求選k個不同的數,和為0的方案數
學到了新姿勢叫整數劃分,具體實現是dp 詳見:https://blog.csdn.net/Vmurder/article/details/42551603
設f[i][j]為j個數和為i的方案數,然後因為互不相同,所以轉移的話有兩種,就是當前j個數全部+1,和當前j個數全部+1並且多填一個1出來,也就是f[i][j]=f[i-j][j]+f[i-j][j-1]
但是這裏要求選的數不能超過n,我們考慮i>n的f中一定有一個大於n的數,我們把這種情況減掉就行了,也就是f[i][j]-=f[i-n-1][j-1]
這是上面那個blog的截圖
#include<iostream> #include<cstdio> using namespace std; const int N=100005; int T,n,m,mod,f[N][15],ans; int read() { int r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } int main() { T=read(); while(T--) { n=read(),m=read(),mod=read(); f[0][0]=1,ans=0; for(int i=1;i<=n*m;i++) for(int j=1;j<=m;j++) { if(i>=j) f[i][j]=(f[i-j][j]+f[i-j][j-1])%mod; if(i>n) f[i][j]=(f[i][j]-f[i-n-1][j-1]+mod)%mod; } for(int i=1;i<=n*m;i++) for(int j=1;j<=m;j++) { ans=(ans+f[i][j]*f[i][m-j])%mod; if(j!=m) ans=(ans+f[i][j]*f[i][m-j-1])%mod; } printf("%d\n",ans+(m==1)); } return 0; }
bzoj 3612: [Heoi2014]平衡【整數劃分dp】