[NOI2015]寿司晚宴

题目描述

思路很妙啊。

开始还在想各种奇奇怪怪的容斥,却发现无从下手。

看到这种与质因子有关的题我们应该自然想到小于\(\sqrt n\)的质因子应该不多。实际上确实不多,只有8个。于是我们就可以状压了。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 505

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

int n,mod;
bool vis[30];
int p[30];

void pre(int n) {
	for(int i=2;i<=n;i++) {
		if(!vis[i]) p[++p[0]]=i;
		for(int j=1;j<=p[0]&&i*p[j]<=n;j++) {
			vis[i*p[j]]=1;
			if(i%p[j]==0) break;
		}
	}
}

int st[N][1<<8];
int sta[N];
ll f[1<<8][1<<8],g[1<<8][1<<8],tem[1<<8][1<<8];
int Mod(int a) {return a<0?a+mod:(a<mod?a:a-mod);}
ll pw2[N];

int main() {
	pre(20);
	n=Get(),mod=Get();
	pw2[0]=1;
	for(int i=1;i<=n;i++) pw2[i]=(pw2[i-1]<<1)%mod;
	for(int i=2;i<=n;i++) {
		int now=i;
		for(int j=1;j<=p[0];j++) {
			if(now%p[j]==0) sta[i]|=1<<j-1;
			while(now%p[j]==0) now/=p[j];
		}
		st[now][sta[i]]++;
	}
	f[0][0]=1;
	for(int i=1;i<=n;i++) {
		if(i==1) {
			for(int now=0;now<1<<8;now++) {
				if(!st[i][now]) continue ;
				memcpy(g,f,sizeof(g));
				for(int s=0;s<1<<8;s++) {
					for(int t=0;t<1<<8;t++) {
						if(!(now&s)) g[s][t|now]=(g[s][t|now]+f[s][t]*(pw2[st[i][now]]-1))%mod;
						if(!(now&t)) g[s|now][t]=(g[s|now][t]+f[s][t]*(pw2[st[i][now]]-1))%mod;
					}
				}
				memcpy(f,g,sizeof(f));
			}
		} else {
			memcpy(tem,f,sizeof(tem));
			memcpy(g,f,sizeof(g));
			for(int now=0;now<1<<8;now++) {
				if(!st[i][now]) continue ;
				memcpy(g,f,sizeof(g));
				for(int s=0;s<1<<8;s++) {
					for(int t=0;t<1<<8;t++) {
						if(!(now&s)) g[s][t|now]=(g[s][t|now]+f[s][t]*(pw2[st[i][now]]-1))%mod;
					}
				}
				memcpy(f,g,sizeof(f));
			}
			memcpy(f,tem,sizeof(f));
			
			memcpy(tem,g,sizeof(g));
			for(int s=0;s<1<<8;s++)
				for(int t=0;t<1<<8;t++)
					tem[s][t]=Mod(tem[s][t]-f[s][t]);
			for(int now=0;now<1<<8;now++) {
				if(!st[i][now]) continue ;
				memcpy(g,f,sizeof(g));
				for(int s=0;s<1<<8;s++) {
					for(int t=0;t<1<<8;t++) {
						if(!(now&t)) g[s|now][t]=(g[s|now][t]+f[s][t]*(pw2[st[i][now]]-1))%mod;
					}
				}
				memcpy(f,g,sizeof(f));
			}
			for(int s=0;s<1<<8;s++)
				for(int t=0;t<1<<8;t++)
					f[s][t]=Mod(f[s][t]+tem[s][t]);
		}
	}
	int ans=0;
	for(int s=0;s<1<<8;s++)
		for(int t=0;t<1<<8;t++)
			ans=Mod(ans+f[s][t]);
	cout<<ans;
	return 0;
}

posted @ 2019-02-25 22:25  hec0411  阅读(213)  评论(0编辑  收藏  举报