萌新刚学OI,状压求调[悬赏一关注]
查看原帖
萌新刚学OI,状压求调[悬赏一关注]
593791
_Catluo_楼主2023/2/15 20:17
#include <bits/stdc++.h>
#define int long long 
using namespace std;
int n,mod,ans;
struct node{
    int x;
    int s;
}a[505];
int z[8]={2,3,5,7,11,13,17,19};
bool cmp(node X,node Y){
    return X.x<Y.x;
}
int f[(1<<8)+5][(1<<8)+5];//储存阶段的状态 
int res[(1<<8)+5][(1<<8)+5][2][2];//存储大的质因数相同的一段 
int now,pre=1;
signed main(){
    f[0][0]=1;
    cin>>n>>mod;
    for(int i=1;i<=n;i++)a[i].x=i+1;
    for(int i=1;i<=n;i++){
        for(int j=7;j>=0;j--){//分解质因数 
            a[i].s<<1;
            if(a[i].x%z[j]==0){
                a[i].s++;
                while(a[i].x%z[j]==0)a[i].x/=z[j]; 
            }
        }
    }
    sort(a+1,a+n+1,cmp);//大于22的质因数排序 
    res[0][0][now][0]=res[0][0][now][1]=1;
    for(int i=1;i<=n;i++){
        for(int j=0;j<(1<<8);j++)
            for(int k=0;k<(1<<8);k++)
                if((j&k)==0)res[j][k][pre][0]=res[j][k][pre][1]=0;
        for(int j=0;j<(1<<8);j++){
            for(int k=0;k<(1<<8);k++){
                if(((j|a[i].s)&k)==0)res[j|a[i].s][k][pre][0]=(res[j|a[i].s][k][pre][0]+res[j][k][now][0])%mod;//给第一个人 
                if((j&k)==0)res[j][k][pre][0]+=(res[j][k][pre][0]+res[j][k][now][0])%mod;//都不吃(1) 
                if((j&(k|a[i].s))==0)res[j][k|a[i].s][pre][1]+=(res[j][k|a[i].s][pre][1]+res[j][k][now][1])%mod;//给第二个人 
                if((j&k)==0)res[j][k][pre][1]+=(res[j][k][pre][1]+res[j][k][now][1])%mod;//都不吃(2) 
            }
        }
        if(a[i].x!=a[i+1].x){
            for(int j=0;j<(1<<8);j++){
                for(int k=0;k<(1<<8);k++){
                    if((j&k)==0){
                        f[j][k]=(res[j][k][now][0]+res[j][k][now][1]-f[j][k]+mod)%mod;//记录下阶段的答案 
                    }
                }
            }
            for(int j=0;j<(1<<8);j++){
                for(int k=0;k<(1<<8);k++){
                    if((j&k)==0){
                        res[j][k][now][0]=res[j][k][now][1]=f[j][k];//覆盖 
                    }
                }
            }
        }
        now=1-now;//滚动 
        pre=1-pre;
    }
    for(int j=0;j<(1<<8);j++)
        for(int k=0;k<(1<<8);k++)
            if((j&k)==0)
                ans=(ans+f[j][k])%mod; 
    cout<<ans<<endl;
    return 0;
}
2023/2/15 20:17
加载中...