测试

测试

  在你的帮助下,(Winedag) 愉快地在$ deadline $前造完了他的题目。
  虽然 (Winedag) 非常牛逼,但 (Wetmath) 还是要求他参加模拟考试。
  (Winedag) 要考的题目一共有 (n) 道,对于第$ i $道题,如果 (AC) 了,那么得分为(i) ,否则得分为(1),这套题的得分为所有题的得分的积,如果没有$ AC$ 任何题,那么得分为 (1)
  就在 (Winedag) 准备切题如麻的时候,突然想起了一个事情,之前有人告诉他:在评测结束以后,会有一个小斗士来把所有分数不为完全平方数的人的程序删掉,分数变为 (0) 分。
  (Winedag) 想知道他有多少种方案能得到他能得到的最高分,但是他忙于写代码,所以他只能来找你帮忙。

显然我们得到最大乘积的方案就是先把所有的数乘起来,然后如果有些质因子出现次数为奇数就将该质因子除去。合法的方案即使选出一些不具有相同质因子数,他们质因子最高次数为(1),并且他们恰好包含了所有需要的质因子。

这种质因子的题大概率是将以(sqrt n)为分界线将质因子分为两个集合然后状压。小于(sqrt {3000})的质因子只有(16)个,于是状压就行了。

代码:

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

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;}

bool vis[N];
int p[N],size[N],n;
int sp[N];
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]&&1ll*i*p[j]<=n;j++) {
			vis[i*p[j]]=1;
			if(i%p[j]==0) break;
		}
	}
}
vector<int>st[N];
ll f[1<<16],g[1<<16];
int main() {
	n=Get();
	pre(n);
	for(int i=1;i<=n;i++) {
		int v=i;
		for(int j=1;j<=p[0];j++) {
			while(v%p[j]==0) {
				size[p[j]]^=1;
				v/=p[j];
			}
		}
	}
	int tot=0;
	for(int i=1,maxx=sqrt(n);i<=p[0]&&p[i]<=maxx;i++) {
		if(size[p[i]]) sp[++sp[0]]=p[i];
	}
	
	for(int i=1;i<=n;i++) {
		int flag=1;
		int sta=0;
		int v=i;
		for(int j=1;j<=sp[0];j++) {
			if(v%sp[j]==0) {
				sta|=1<<j-1;
				v/=sp[j];
				if(v%sp[j]==0) {flag=0; break;}
			}
		}
		if(!flag) continue ;
		if(v>1&&(vis[v]||!size[v])) continue ;
		st[v].push_back(sta);
	}
	f[0]=1;
	for(int i=0;i<st[1].size();i++) {
		memcpy(g,f,sizeof(g));
		for(int S=0;S<1<<sp[0];S++)
			if((st[1][i]&S)==st[1][i])
				g[S]+=f[S^st[1][i]];
		memcpy(f,g,sizeof(f));
	}
	for(int i=2;i<=n;i++) {
		if(!st[i].size()) continue ;
		memset(g,0,sizeof(g));
		for(int j=0;j<st[i].size();j++) {
			for(int S=0;S<1<<sp[0];S++)
				if((st[i][j]&S)==st[i][j])
					g[S]+=f[S^st[i][j]];
		}
		memcpy(f,g,sizeof(f));
	}
	cout<<f[(1<<sp[0])-1];
	return 0;
}

原文地址:https://www.cnblogs.com/hchhch233/p/10503240.html