51nod 1201 整数划分 1259 整数划分 V2

前言

今天在家颓了一天。。
为了证明自己还是有点用的,所以来补一篇博客
然而还是改不了今天颓了一天的事实

明天就要回去上文化课了。。什么都不会呢
感觉省选GG以后一连颓了很多天呢
好吧,省选的时候也在颓

1201 整数划分

将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2,3},共4种。由于数据较大,输出Mod 10^9 + 7的结果即可。

我们发现到,他所要用到的数,级别是根号的
于是我们可以设计DP
f [ i ] [ j ] 表示用了i个数,和为j的方案
转移比较巧妙
为了不重复计算
我们认为规定,我们最后搞出来的序列是单调下降的
然后有两种转移,第一种是使得这 i 个数全部 + 1 ,第二种是,在让这 i 个数全部加一后在末尾添加一个新的数 1
容易知道,这样是可以不重不漏地构造出所有方案的
于是这题就解决了
CODE:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
const LL N=50005;
LL f[321][N];
int main()
{
    LL n;
    scanf("%lld",&n);
    f[0][0]=1;
    LL ans=0;
    for (LL u=1;u<=320;u++) 
    {
        for (LL i=u;i<=n;i++)//用了u个数,凑出i有多少种方案 
        {
            f[u][i]=(f[u-1][i-u]+f[u][i-u])%MOD;
        }
        ans=(ans+f[u][n])%MOD;
    }
    printf("%lld\n",ans);
    return 0;
}

1259 整数划分 V2

由于这题的数字可以重复,所以上面那个做法就GG了。。
但是思路还是可以用的
我们考虑分块DP
我们可以DP两个东西
一个是使用 n 以内的数,凑出 i 的方案 f [ i ]
一个是使用 n 以外的数,凑出 i 的方案 g [ i ]
然后两个东西卷积起来, n 的位置就是答案了
对于前者,我们可以直接背包DP
然后后者,我们可以用上面那题的方法来做
因为他用的个数也是根号级别的
然后只需要把每一次补一个 1 ,改为补一个 n + 1 就可以了

CODE:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
const LL N=50005;
LL f[2][N];//用了前i个数,和为j的方案 
LL g[2][N];
LL h[N];
LL n,m;
int main()
{
    scanf("%lld",&n);m=sqrt(n);
    f[0][0]=1;
    int now=0,now1=0;
    for (LL u=1;u<=m;u++)
    {
        now^=1;
        for (LL i=0;i<u;i++) f[now][i]=f[now^1][i];
        for (LL i=u;i<=n;i++) f[now][i]=(f[now][i-u]+f[now^1][i])%MOD;
    }
    m++;
    g[0][0]=1;h[0]=1;
    for (LL u=1;u<=m;u++)
    {
        now1^=1;
        for (LL i=0;i<=n;i++)
        {
            g[now1][i]=0;
            if (i>=m) g[now1][i]=(g[now1][i]+g[now1^1][i-m])%MOD;//假如一个根号n
            if (i>=u) g[now1][i]=(g[now1][i]+g[now1][i-u])%MOD;//全部数+1
            h[i]=(h[i]+g[now1][i])%MOD;
        }
    }
    LL ans=0;
    for (LL u=0;u<=n;u++)   ans=(ans+f[now][u]*h[n-u]%MOD)%MOD;
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36797743/article/details/80210332
今日推荐