HDU 4602 Partition
f[i]表示和为i的方案数。已知f[i]=2i-1。
dp[i]表示和为i,k有多少个。那么dp[i]=dp[1]+dp[2]+...+dp[i-1]+f[i-k]。
考虑与f有关的项:
f[n-k]是答案的一部分,即2n-k-1是答案的一部分。
把与dp有关的项:
令s[i-1]=dp[1]+dp[2]+...+dp[i-1],那么s[n-1]是答案的一部分。
s[i]=s[i-1]+dp[i],又dp[i]=s[i-1]+f[i-k]。推出s[i]=2*s[i-1]+f[i-k],dp[k]=s[k]=1。
可以推出s[n-1]=2n-k-1+(n-k-1)*2n-k-2。
1 #include<iostream> 2 typedef long long LL; 3 LL MOD = 1000000007LL; 4 using namespace std; 5 LL powmod(LL a, LL b) { 6 LL ans; 7 a %= MOD; 8 for (ans = 1; b; b >>= 1) { 9 if (b & 1) { 10 ans *= a; 11 ans %= MOD; 12 } 13 a *= a; 14 a %= MOD; 15 } 16 return ans; 17 } 18 int main() { 19 int T; 20 LL n, k; 21 LL ans; 22 cin >> T; 23 while (T--) { 24 cin >> n >> k; 25 if (k > n) { 26 ans = 0; 27 } else if (k == n) { 28 ans = 1; 29 } else if (n - k == 1) { 30 ans = 2; 31 } else if (n - k == 2) { 32 ans = 5; 33 } else { 34 ans = powmod(2, n - k - 1) 35 + (n - k - 1) * powmod(2, n - k - 2) % MOD; 36 ans += powmod(2, n - k - 1); 37 ans = (ans % MOD + MOD) % MOD; 38 } 39 cout << ans << endl; 40 } 41 return 0; 42 }