求个助
查看原帖
求个助
344409
_stardust_楼主2021/1/30 10:54

这题写挺久了。。。然后最近重构了一遍代码,始终过不了样例,求有闲心的同学帮忙看一下,谢谢。

大致思路写注释里了。

/*
暴力就f[i][s1][s2],转移f[i+1][s1|k][s2]+=f[i][s1][s2],f[i+1][s1][s2|k]+=f[i][s1][s2]。
大质因子最多一个,单独拿出来做dp。onedp[i][s1][s2]表示第一个人选了这个大因子,anodp同理。
然后合并答案dp[i][s1][s2]=onedp+anodp-dp
*/
#include<cstdio>
#include<algorithm>
using namespace std;
const int up=1<<8;
int n,p,onedp[2][(1<<8)+5][(1<<8)+5],anodp[2][(1<<8)+5][(1<<8)+5],dp[2][(1<<8)+5][(1<<8)+5],turn,ans;
int pri[10]={2,3,5,7,11,13,17,19};
struct node
{
	int lar,nor;
}num[510];
bool cmp(node one,node ano)
{
	return one.lar<ano.lar;
}
int main()
{
	// freopen("test.out","w",stdout);
	scanf("%d%d",&n,&p);
	n--;
	for(int i=1;i<=n;++i)
	{
		int tmp=i+1;
		for(int j=0;j<8;++j)
		{
			if(tmp%pri[j]==0)
			{
				while(tmp%pri[j]==0)	tmp/=pri[j];
				num[i].nor|=(1<<j);
			}
		}
		num[i].lar=tmp;
	}
	sort(num+1,num+n+1,cmp);
	dp[0][0][0]=1;
	for(int i=1;i<=n;++i)
	{
		if(i==1||num[i].lar==1||(num[i].lar^num[i-1].lar))
		{
			for(int j=0;j^up;++j)
			{
				for(int k=0;k^up;++k)
				{
					onedp[turn][j][k]=dp[turn][j][k];
					anodp[turn][j][k]=dp[turn][j][k];
				}
			}
		}
		for(int j=0;j^up;++j)
		{
			for(int k=0;k^up;++k)
			{
				if(!(j&k))
				{
					if(!(num[i].nor&j))
					{
						anodp[turn^1][j][k|num[i].nor]=(anodp[turn^1][j][k|num[i].nor]+anodp[turn][j][k])%p;
						// printf("%d %d %d %d\n",j,k,anodp[turn^1][j][k|num[i].nor],anodp[turn][j][k]);
					}
					if(!(num[i].nor&k))	onedp[turn^1][j|num[i].nor][k]=(onedp[turn^1][j|num[i].nor][k]+onedp[turn][j][k])%p;
					// printf("%d %d\n",anodp[turn^1][j][k],onedp[turn^1][j][k]);
				}
			}
		}
		if(i==n||num[i].lar==1||(num[i].lar^num[i+1].lar))
		{
			for(int j=0;j^up;++j)
			{
				for(int k=0;k^up;++k)
				{
					if(!(j&k))	dp[turn^1][j][k]=(onedp[turn^1][j][k]+anodp[turn^1][j][k]-dp[turn][j][k]+p)%p;
				}
			}
		}
		turn^=1;
	}
	for(int i=0;i^up;++i)
	{
		for(int j=0;j^up;++j)
		{
			if(!(i&j))	ans=(ans+dp[turn][i][j])%p;
		}
	}
	printf("%d\n",ans);
	return 0;
}

如果是哪里手残了请不吝赐教。

2021/1/30 10:54
加载中...