• CF1622F Quadratic Set


    一、题目

    点此看题

    二、解法

    首先手玩可以得到一个貌似没什么用的性质,也就是最后是否是平方数取决于 \(\prod_{k\geq 0}(n-2k)\) 是否是平方数,由于我们还想要更简单的形式,这里我们不妨先只考虑 \(n\) 为偶数的情况:

    \[\prod_{0<2k\leq n} 2k=2^{n/2}\cdot (n/2)! \]

    那么我们在最坏情况下也只需要删除 \(2,n/2,n\) 这三项就可以获得构造,这说明答案的下界为 \(3\),所以我们只需要讨论答案是否为 \(0/1/2\),剩下的情况就给出 \(3\) 的上述构造即可。

    \(0\) 可以直接判断乘积是不是完全平方数,直接对 \(\prod_{k\geq 0} (n-2k)\) 质因数分解即可;\(1\) 就需要找出质因数分解和上式相同的一个数,可以用哈希判断,就是给每个质因子分配一个 \(\tt ull\) 之内的整数,然后判断异或和是否相等即可;\(2\) 可以加上 \(\tt unordered\_map\) 来找异或和相等的点对。

    三、总结

    注意构造题有这样一种情况,也就是当答案范围很小的时候我们可以用讨论法解决问题,排除掉所有简单情况之后剩下的就是那种较复杂的情况。

    #include <cstdio>
    #include <cstdlib>
    #include <unordered_map>
    #include <ctime>
    using namespace std;
    const int M = 1000005;
    #define ull unsigned long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,cnt,mn[M],a[M],p[M],vis[M];ull v[M],h[M];
    unordered_map<ull,int> mp;
    int random(int x)
    {
    	return (rand()*rand()+rand())%x;
    }
    void init()
    {
    	for(int i=2;i<=n;i++)
    	{
    		if(!vis[i]) p[++cnt]=i,mn[i]=i;
    		for(int j=1;j<=cnt && i*p[j]<=n;j++)
    		{
    			vis[i*p[j]]=1;mn[i*p[j]]=p[j];
    			if(i%p[j]==0) break;
    		}
    	}
    }
    signed main()
    {
    	n=read();init();srand(time(0));
    	for(int i=1;i<=n;i++)
    		v[i]=1ll*random(2e9)*random(2e9)+random(2e9);
    	for(int i=n;i>=1;i-=2)
    	{
    		int x=i;
    		while(x>1)
    		{
    			int p=mn[x];
    			while(x%p==0) x/=p,a[p]^=1;
    		}
    	}
    	int fl=1;for(int i=1;i<=n;i++) fl&=!a[i];
    	if(fl)
    	{
    		printf("%d\n",n);
    		for(int i=1;i<=n;i++)
    			printf("%d ",i);
    		puts("");return 0;
    	}
    	ull hs=0;
    	for(int i=1;i<=n;i++) if(a[i]) hs^=v[i];
    	for(int i=1;i<=n;i++)
    	{
    		int x=i;
    		while(x>1)
    		{
    			int p=mn[x];
    			while(x%p==0) x/=p,h[i]^=v[p];
    		}
    		h[i]^=h[i-1];
    		if(h[i]==hs)
    		{
    			printf("%d\n",n-1);
    			for(int j=1;j<=n;j++) if(j!=i)
    				printf("%d ",j);
    			puts("");return 0;
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		if(mp.count(hs^h[i]))
    		{
    			int j=mp[hs^h[i]];
    			printf("%d\n",n-2);
    			for(int k=1;k<=n;k++) if(k!=i && k!=j)
    				printf("%d ",k);
    			puts("");return 0;
    		}
    		mp[h[i]]=i;
    	}
    	printf("%d\n",n-3);
    	for(int i=1;i<n;i++) if(i!=2 && i!=n/2)
    		printf("%d ",i);
    	puts("");return 0;
    }
    
  • 相关阅读:
    eclipse新建工作空间后的常用设置
    Maven将代码及依赖打成一个Jar包的方式
    MemCache详细解读(转)
    memcached单机或热备的安装部署
    memcache的基本操作
    Java中int和String类型之间转换
    Linux中普通用户配置sudo权限(带密或免密)
    Java字符串中常用字符占用字节数
    java各种数据类型的数组元素的默认值
    validator
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15813640.html
Copyright © 2020-2023  润新知