51Nod 1259 - 整數劃分 V2(五邊形數定理)
阿新 • • 發佈:2018-11-08
【題目描述】
【思路】
大佬的部落格
記板子
#include<bits/stdc++.h> #define f(x)(((x)*(3*(x)-1))>>1) #define g(x)(((x)*(3*(x)+1))>>1) using namespace std; const int mod=1e9+7; const int maxn=100005; int n,ans[maxn]; int main(){ scanf("%d",&n); ans[0]=1; for(int i=1;i<=n;++i){ for(int j=1;f(j)<=i;++j) if(j&1) ans[i]=((long long)ans[i]+ans[i-f(j)])%mod; else ans[i]=(((long long)ans[i]-ans[i-f(j)])%mod+mod)%mod; for(int j=1;g(j)<=i;++j) if(j&1) ans[i]=((long long)ans[i]+ans[i-g(j)])%mod; else ans[i]=(((long long)ans[i]-ans[i-g(j)])%mod+mod)%mod; } printf("%d\n",ans[n]); return 0; }
拓展
// 問一個數n能被拆分成多少種情況 // 且要求拆分元素重複次數不能≥k const int MOD = 1e9 + 7; const int MAXN = 1e5 + 10; int ans[MAXN]; // 此函式求ans[]效率比上一個程式碼段中求ans[]效率高很多 void init() { memset(ans, 0, sizeof(ans)); ans[0] = 1; for (int i = 1; i < MAXN; ++i) { ans[i] = 0; for (int j = 1; ; j++) { int tmp = (3 * j - 1) * j / 2; if (tmp > i) { break; } int tmp_ = ans[i - tmp]; if (tmp + j <= i) { tmp_ = (tmp_ + ans[i - tmp - j]) % MOD; } if (j & 1) { ans[i] = (ans[i] + tmp_) % MOD; } else { ans[i] = (ans[i] - tmp_ + MOD) % MOD; } } } return ; } int solve(int n, int k) { int res = ans[n]; for (int i = 1; ; i++) { int tmp = k * i * (3 * i - 1) / 2; if (tmp > n) { break; } int tmp_ = ans[n - tmp]; if (tmp + i * k <= n) { tmp_ = (tmp_ + ans[n - tmp - i * k]) % MOD; } if (i & 1) { res = (res - tmp_ + MOD) % MOD; } else { res = (res + tmp_) % MOD; } } return res; } int main(int argc, const char * argv[]) { init(); int T, n, k; cin >> T; while (T--) { cin >> n >> k; cout << solve(n, k) << '\n'; } return 0; }