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


    参考资料

    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
    ",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
    ",++ca,ans);
    55 
    56     
    57     }
    58 
    59 }
    HDU6042
  • 相关阅读:
    ACM学习历程——POJ3321 Apple Tree(搜索,线段树)
    ACM学习历程——NOJ1113 Game I(贪心 || 线段树)
    ACM学习历程——HDU5202 Rikka with string(dfs,回文字符串)
    ACM学习历程——hihoCoder挑战赛10A 01串(策略)
    ACM学习历程——POJ3468 A Simple Problem with Integers(线段树)
    ACM学习历程——POJ1260 Pearls(动态规划)
    java入门了解09
    java入门了解08
    java入门了解之快捷键
    java入门了解07
  • 原文地址:https://www.cnblogs.com/greenty1208/p/9941891.html
Copyright © 2020-2023  润新知