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 }
View Code

 

posted @ 2017-09-27 19:02  geloutingyu  阅读(455)  评论(0编辑  收藏  举报