【笔记】生成函数与大背包问题

参考资料

https://blog.csdn.net/lchi1997/article/details/77860085

五边形数和分拆数模板

ll p[100005];
ll q[200005];
const ll mod = 1e9+7;
void init() {
    int tot = 0;
    q[0] = 0;
    int cnt=0;
    for(int i=1;i<=100000;i++) { 
    ll x=i;
    q[++cnt] =( (ll)x*(3*x-1)/2)%mod;
    x = -x;
    q[++cnt] =( (ll)x*(3*x-1)/2)%mod;
    }
    p[0]=1;
    for(int i=1;i<=100000;i++){
    for(int now = 1,o=1;i-q[now]>=0;now++){
        p[i] += o*(p[i-q[now]]);
        p[i] %=mod;
        if((now&1)==0) o=-o; 
    }
    if(p[i]<0)p[i]+=mod;
    }
}
View Code

HDU 4658

题意:

给定n,k, 将数字n划分为若干数字之和,每种数字出现次数小于k,求方案数

思路:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 ll p[100005];
 5 ll q[200005];
 6 const ll mod = 1e9+7;
 7 void init() {
 8     int tot = 0;
 9     q[0] = 0;
10     int cnt=0;
11     for(int i=1;i<=100000;i++) { 
12     ll x=i;
13     q[++cnt] =( (ll)x*(3*x-1)/2)%mod;
14     x = -x;
15     q[++cnt] =( (ll)x*(3*x-1)/2)%mod;
16     }
17     p[0]=1;
18     for(int i=1;i<=100000;i++){
19     for(int now = 1,o=1;i-q[now]>=0;now++){
20         p[i] += o*(p[i-q[now]]);
21         p[i] %=mod;
22         if((now&1)==0) o=-o; 
23     }
24     if(p[i]<0)p[i]+=mod;
25     }
26 }
27 int main(){
28     init();
29     int _,n,k;scanf("%d",&_);
30     while(_--) {
31     scanf("%d%d",&n,&k);
32     int o=1;
33     ll ans=0;
34     for(int i=0;q[i]*k<=n;i++){
35         ans+=o*p[n-q[i]*k];
36         ans%=mod;
37         if((i&1)==0) o=-o;
38     }
39     if(ans<0)ans+=mod;
40     printf("%lld\n",ans);
41     }
42 }
HDU4658
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 ll p[100005];
 5 ll q[200005];
 6 const ll mod = 1e9+7;
 7 void init() {
 8     q[0] = 0;
 9     int cnt=0;
10     for(int i=1;i<=100000;i++) { 
11         ll x=i;
12         q[++cnt] =((ll)x*(3*x-1)/2)%mod;
13         x = -x;
14         q[++cnt] =((ll)x*(3*x-1)/2)%mod;
15     }
16     p[0]=1;
17     for(int i=1;i<=100000;i++){
18     for(int now = 1,o=1;i-q[now]>=0;now++){
19         p[i] += o*(p[i-q[now]]);
20         p[i] %=mod;
21         if((now&1)==0) o=-o; 
22     }
23     if(p[i]<0)p[i]+=mod;
24     }
25 }
26 ll a[50005],b[100005],n,m;
27 ll f[100005];
28 int main(){
29     init();
30     int ca=0;
31     while(scanf("%lld%lld",&n,&m)!=EOF){
32     for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
33     for(int i=1;i<=m;i++) scanf("%lld",&b[i]);
34     for(int i=0;i<=n;i++) f[i]=p[i];
35     ll s=0;
36     for(int i=n+1,j=0;i<=n+n;i++,j++){
37         s+=p[j];if(s>=mod)s-=mod;
38         f[i] = p[i] - s;
39         if(f[i]<0) f[i]+=mod;
40     }
41     for(int i=1;i<=n;i++){
42         if(a[i]*i+i<=2*n){
43         for(int j=n+n;j>=a[i]*i+i;j--) {
44             f[j] -= f[j-(a[i]+1)*i];
45             while(f[j]<0)f[j]+=mod; 
46         }
47         }
48     }
49     ll ans=0;
50     for(int i=1;i<=m;i++){
51         ans+=f[n+n-b[i]];
52         if(ans>mod)ans-=mod;
53     }
54     printf("Case #%d: %lld\n",++ca,ans);
55 
56     
57     }
58 
59 }
HDU6042

 

posted @ 2018-11-11 15:26  Greenty  阅读(469)  评论(0编辑  收藏  举报