bzoj 4197: [Noi2015]寿司晚宴【状压dp】

一个数内可能多个的质因数只有小于根号n的,500内这样的数只有8个,所以考虑状压

把2~n的数处理出小于根号500的质因数集压成s,以及大质数p(没有就是1),然后按p排序

根据题目要求,拥有一个质因数的只能给一个人,所以排序后能给一个人的大质数就是一个区间

然后设f[s1][s2]为一人选s1,另一人选s2的方案数,注意这里的s只压了小于根号500的八个质数

设g[0/1][s1][s2]为一人选s1,另一人选s2的,当前枚举的大质数给小G/小W的方案数

正常转移即可

然后注意把g转到f上时应该是f[j][k]=g[0][j][k]+g[1][j][k]-f[j][k],也就是减掉被算了两次的,当前枚举大质数都不选的情况

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=505,p[]={2,3,5,7,11,13,17,19};
int n;
long long mod,f[N][N],g[2][N][N],ans;
bool v[N];
struct qwe
{
    int s,p;
}a[N];
bool cmp(const qwe &a,const qwe &b)
{
    return a.p<b.p;
}
int main()
{
    scanf("%lld%lld",&n,&mod);
    for(int i=2;i<=n;i++)
    {
        int x=i;
        for(int j=0;j<8;j++)
            if(x%p[j]==0)
            {
                a[i].s|=(1<<j);
                while(x%p[j]==0)
                    x/=p[j];
            }
        a[i].p=x;
    }
    sort(a+2,a+1+n,cmp);
    f[0][0]=1;
    for(int i=2;i<=n;i++)
    {
        if(i==2||a[i].p!=a[i-1].p||a[i].p==1)
        {
            memcpy(g[0],f,sizeof(f));
            memcpy(g[1],f,sizeof(f));
        }
        for(int j=255;j>=0;j--)
            for(int k=255;k>=0;k--)
                if(!(j&k))
                {
                    if(!(a[i].s&k))
                        g[0][a[i].s|j][k]=(g[0][a[i].s|j][k]+g[0][j][k])%mod;
                    if(!(a[i].s&j))
                        g[1][j][a[i].s|k]=(g[1][j][a[i].s|k]+g[1][j][k])%mod;
                }
        if(i==n||a[i].p==1||a[i].p!=a[i+1].p)
            for(int j=255;j>=0;j--)
                for(int k=255;k>=0;k--)
                    if(!(j&k))
                        f[j][k]=(g[0][j][k]+g[1][j][k]-f[j][k])%mod;
    }
    for(int i=255;i>=0;i--)
        for(int j=255;j>=0;j--)
            if(!(i&j))
                ans=(ans+f[i][j])%mod;
    printf("%lld\n",(ans+mod)%mod);
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/9700425.html

时间: 2024-10-20 06:51:42

bzoj 4197: [Noi2015]寿司晚宴【状压dp】的相关文章

【BZOJ4197】[Noi2015]寿司晚宴 状压DP+分解质因数

[BZOJ4197][Noi2015]寿司晚宴 Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n−1 种不同的寿司,编号 1,2,3,…,n−1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n). 现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当:小 G 品尝的寿司种类中存在一种美味度为 x

BZOJ 4197 NOI 2015 寿司晚宴 状压DP

4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 694  Solved: 440[Submit][Status][Discuss] Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n?1 种不同的寿司,编号 1,2,3,-,n?1,其中第 i 种寿司的美味度为 i+1 (即

BZOJ 4197: [Noi2015]寿司晚宴( dp )

N^0.5以内的质数只有8个, dp(i, j, k)表示用了前i个大质数(>N^0.5), 2人选的质数(<=N^0.5)集合分别为j, k时的方案数. 转移时考虑当前的大质数p是给哪个人即可. 时间复杂度O(N*2^16) ----------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm&

[BZOJ]4197: [Noi2015]寿司晚宴

Time Limit: 10 Sec  Memory Limit: 512 MB Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n?1 种不同的寿司,编号 1,2,3,-,n?1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n). 现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当:小 G 品尝

【dp】【NOI 2015】【bzoj 4197】寿司晚宴

4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 58 Solved: 46 Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n?1 种不同的寿司,编号 1,2,3,-,n?1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n). 现在小 G 和小 W

bzoj 1556: 墓地秘密【状压dp+spfa】

显然是状压,显然不可能把所有格子压起来 仔细观察发现只有机关周围的四个格子有用以及起点,所以我们用spfa处理出这些格子两两之间的距离(注意细节--这里写挂了好几次),然后设f[s][i]为碰完的机关石状态为s,现在在有用格子的第i个的最小停下次数,转移按照套路即可 #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const

BZOJ 4145: [AMPPZ2014]The Prices( 状压dp + 01背包 )

我自己只能想出O( n*3^m )的做法....肯定会T O( nm*2^m )做法: dp( x, s ) 表示考虑了前 x 个商店, 已买的东西的集合为s. 考虑转移 : 先假设我们到第x个商店去, so初始时 dp( x, s) = dp( x-1, s ) + d[x] 然后我们可以对第x个商店做01背包, dp(x, s + {h} ) = min( dp( x, s + {h} ) , dp( x, s) + c[x][h]) ) ( h ∉ s ). 之后我们再比较到第x个商店划不

BZOJ 1072 SCOI2007 排列perm 状压DP

题目大意:给定n个数字,求这些数字的全排列中有多少数能被d整除 令f[i][j]为状态为i,余数为j的方案数 枚举最高位转移 小心爆int #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,d,ans,f[1<<10][1<<10],digit[1<<10],tens[10

BZOJ 4145 AMPPZ2014 The Prices 状压DP

题目大意:给定n个商店和m种物品,你需要每种物品买一个,去第i个商店的路费是di,第i个商店出售第j种物品的价格是ci,j,求最小花销 令fi,j表示当前已经考虑了前i个商店,购买的状态为j的最小花销 然后每个商店内跑个背包即可 时间复杂度O(nm2m) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int