hdu4658(广义五边形&分割函数2)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4658
题意:f(x) 为将 x 分成其他数和的形式的方案数.对于 t 组输入,输出 f(xi, k), 其中 k 表示 xi 分解的数出现的次数不超过 k 次.
思路:在 hdu4651(http://www.cnblogs.com/geloutingyu/p/7599415.html) 的基础上加个限制 k.
感觉公式好难推,直接当模板用好了.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 const int mod = 1e9 + 7; 6 const int MAXN = 1e5 + 1; 7 int f[MAXN]; 8 9 void get_f(void){ 10 f[0] = 1; 11 for(int i = 1; i < MAXN; i++){ 12 for(int j = 1, cnt = 1; i - (3 * j * j - j) / 2 >= 0; j++, cnt *= -1){ 13 int cc = 3 * j * j; 14 f[i] += f[i - (cc - j) / 2] * cnt; 15 f[i] %= mod; 16 f[i] = (f[i] + mod) % mod; 17 if(i >= (cc + j) / 2){ 18 f[i] += f[i - (cc + j) / 2] * cnt; 19 f[i] %= mod; 20 f[i] = (f[i] + mod) % mod; 21 } 22 } 23 } 24 } 25 26 int solve(int n, int k){ 27 int ans = f[n]; 28 for(int i = 1, cnt = -1; n - k * (3 * i * i - i) / 2 >= 0; i++, cnt *= -1){ 29 ans += f[n - k * (3 * i * i - i) / 2] * cnt; 30 ans %= mod; 31 ans = (ans + mod) % mod; 32 if(n - k * (3 * i * i + i) / 2 >= 0){ 33 ans += f[n - k * (3 * i * i + i) / 2] * cnt; 34 ans %= mod; 35 ans = (ans + mod) % mod; 36 } 37 } 38 return ans; 39 } 40 41 int main(void){ 42 get_f(); 43 int t, x, k; 44 scanf("%d", &t); 45 while(t--){ 46 scanf("%d%d", &x, &k); 47 printf("%d\n", solve(x, k)); 48 } 49 return 0; 50 }
我就是我,颜色不一样的烟火 --- geloutingyu