壽司晚宴題解

壽司晚宴題解

先理解一下題目吧:
兩人所選數的質因數集合不能有交集,
<=30的質數只有10個,因此能夠直接狀壓,
\(dp[i][j]\)表明第一我的選的狀態爲i,第二我的的狀態爲j的方案數,
100%:n由30拓展到了500,怎麼辦?
考慮到<=500的數最多隻有1個大於\(sqrt(500)>22\)的大質因子,
咱們能夠按大質因子排序,想同的大質因子裏用,用dp表示選了它的狀況,用dp2表示沒選的狀況,而後轉移,
不一樣的時候就繼承以前的值.c++

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int M=506,N=266;
int n,m,tot=0,book[M],prime[M];
ll ans=0,p,f[N][N],dp[N][N],dp2[N][N];
struct xd{int a,b;}q[M];
void init(){
    for(int i=2;i<=500;++i){
        if(!book[i]) prime[++tot]=i;
        for(int j=1;j<=tot&&i*prime[j]<=500;++j){
            book[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
bool cmp(xd u,xd v){return u.b<v.b;}
int main(){
    scanf("%d%lld",&n,&p),m=255,init();
    for(int i=2;i<=n;++i){
        for(int j=9;j<=tot;++j) if(i%prime[j]==0) q[i-1].b=prime[j];
        for(int j=0;j<=7;++j) if(i%prime[j+1]==0) q[i-1].a+=(1<<j);
    }
    sort(q+1,q+n,cmp),f[0][0]=1,q[0].b=q[n].b=-1;
    for(int i=1;i<n;++i){
        if(q[i].b!=q[i-1].b||!q[i].b) memcpy(dp,f,sizeof(dp)),memcpy(dp2,f,sizeof(dp2));
        for(int j=m;j>=0;--j)
            for(int k=m;k>=0;--k){
                if(j&k) continue;
                if(!(q[i].a&k)) dp[j|q[i].a][k]=(dp[j|q[i].a][k]+dp[j][k])%p;
                if(!(q[i].a&j)) dp2[j][k|q[i].a]=(dp2[j][k|q[i].a]+dp2[j][k])%p;
            }
        if(q[i].b!=q[i+1].b||!q[i].b) for(int j=m;j>=0;--j) for(int k=m;k>=0;--k) f[j][k]=(dp[j][k]+dp2[j][k]-f[j][k]+p)%p;
    }
    for(int i=m;i>=0;--i) for(int j=m;j>=0;--j) ans=(ans+f[i][j])%p;
    printf("%lld\n",ans);
    return 0;
}
相關文章
相關標籤/搜索