【DP】[JZOJ4390] 图计数(整数划分)

Description

这里写图片描述
这里写图片描述

Solution

设将n划分为若干个无序正整数之和的方案数为s
可以看出答案就是 ms m s

n=n n ′ = n
分成两个问题,一个是用小于等于 n n ′ 的数来拼和用大于 n n ′ 的数来拼,最后再卷积到一起
小于等于 n n ′ 的部分就是一个完全背包问题

大于 n n ′ 的部分,总的选择个数不会超过 n n ′
可以考虑这样一个DP,每次要么加入一个 n+1 n ′ + 1 ,要么把以前加入所有的数都+1

这样就在 O(nn) O ( n n ) 的复杂度解决了

Code

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 200005
#define M 450
#define LL long long
#define mo 999999599
using namespace std;
LL f[N],g[2][N],h[N];
int bz[2][N];
int n,m;
LL ksm(LL k,LL n)
{
    LL s=1;
    for(;n;n>>=1,k=k*k%mo) if(n&1) s=s*k%mo;
    return s;
}
int main()
{
    cin>>n>>m;
    f[0]=1;
    int n1=sqrt(n);
    fo(i,1,n1)
    {
        fo(j,i,n) 
            f[j]=(f[j]+f[j-i])%(mo-1);
    }   
    g[0][0]=1;
    int i1=0;
    LL s=0;
    fo(i,1,n1)
    {
        i1=1-i1;
        fo(j,(n1+1)*i,n)
        {
            if(bz[i1][j-i]!=i) bz[i1][j-i]=i,g[i1][j-i]=0;
            if(bz[1-i1][j-n1-1]!=i-1) bz[1-i1][j-n1-1]=i-1,g[1-i1][j-n1-1]=0;

            g[i1][j]=(g[i1][j-i]+g[1-i1][j-n1-1])%(mo-1);
            bz[i1][j]=i;
            h[j]=(h[j]+g[i1][j])%(mo-1);
        }
    }
    h[0]=1;
    fo(i,0,n) 
        s=(s+f[i]*h[n-i]%(mo-1))%(mo-1);
    printf("%lld\n",ksm(m,s));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值