【BZOJ4197】寿司晚宴,状态压缩DP

Time:2016.06.29
Author:xiaoyimi
转载注明出处谢谢


传送门
思路:
比较巧妙的处理方法
关于互质这个问题很多都是出现在数论题目里
显然这个不是……
看到500这个数据范围,我首先想到的是网络流,咳咳……
好吧这也不是(用脚趾头都能想出来如果是网络流的话会让你求方案数+取模?)
500=22.36...
这个范围内的质数只有8个
似乎可以状压了吧……
也就是说,我们把两个人所吃的寿司看做是两个质数(实际上是质因子)的集合,一个人吃一个寿司就往这个人的集合里扔若干个质因子,只要这其中没有公共的质数就可以了
大于22的质数怎么办……
每个数最多只有一个大于22的质因子,拆解出来,排序分开计算了,把大于22的相同的质因子的数放到一起去
DP的方法也很巧妙……
类似背包那样做,避免重复计算
f=g+h-f
(因为g,h中各有一个之前的f值)
算了我还是先去食堂抢饭了
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,mo,ans;
int f[256][256],g[256][256],h[256][256],p[9]={0,2,3,5,7,11,13,17,19};
struct node{
    int k,fac;
}a[502];
bool cmp(node a,node b){return a.k<b.k;}
void cal(node &x,int num)
{
    for (int i=1;i<=8;i++)
        if (num%p[i]==0)
        {
            x.fac|=1<<i-1;
            while (num%p[i]==0) num/=p[i];
        }
    x.k=num;
}
main()
{
    scanf("%d%d",&n,&mo);
    for (int i=2;i<=n;i++)
        cal(a[i],i);
    sort(a+2,a+n+1,cmp);
    f[0][0]=1;
    for (int v=2;v<=n;v++)
    {
        if (a[v].k!=a[v-1].k||a[v].k==1)
            for (int i=255;i>=0;i--)
                for (int j=255;j>=0;j--)
                if (!(i&j)) g[i][j]=h[i][j]=f[i][j];
        for (int i=255;i>=0;i--)
            for (int j=255;j>=0;j--)
            if (!(i&j))
            {
                    if (!(a[v].fac&j)) g[i|a[v].fac][j]=(g[i][j]+g[i|a[v].fac][j])%mo;
                    if (!(a[v].fac&i)) h[i][j|a[v].fac]=(h[i][j]+h[i][j|a[v].fac])%mo;
            }
        if (a[v].k!=a[v+1].k||a[v].k==1)
            for (int i=255;i>=0;i--)
                for (int j=255;j>=0;j--)
                    if (!(i&j)) f[i][j]=((g[i][j]+h[i][j])%mo-f[i][j])%mo;
    }
    for (int i=255;i>=0;i--)
        for (int j=255;j>=0;j--)
            if (!(i&j))
                ans=(ans+f[i][j])%mo;
    printf("%d",(ans%mo+mo)%mo); 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值