【LOJ #2978】【PKUSCH 2017】—杜老师(线性基+Bitset+结论题)

传送门


完全平方数说白了就是每个质因子出现了偶数次

所以这道题就是:

给你nn个集合
问有多少种集合选的方案使得集合异或为空

考虑由于大于n\sqrt n的质因子只有11
所以直接按最大质因子分组后需要考虑的数就只有r\sqrt r以内的

筛一下就只有460460个左右

所以把每个质因子奇偶看做二进制位
就相当于选出数使得异或和为0
就相当于构建一个线性基,答案就是22^{自由基的个数}

可以用bitsetbitset优化一下
复杂度O(lenC2/64)O(len*C^2/64)

而题解说如果lenlen在大概66006600以上的时候线性基是满的
所以这时候答案就是2rl+12^{r-l+1-质数个数}

然后就跑的飞快了

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ob==ib)?EOF:*ib++;
}
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
const int mod=998244353,g=3;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a=add(a,b);}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline void Dec(int &a,int b){a=dec(a,b);}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=10000007;
cs int M=460;
#define bit bitset<M>
bitset<N> vis;
bit bas[M],now;
int q[N],pr[N],tot,V,id[N],mxp[N],pnum,ans;
int n,siz;
inline void init(){
	V=sqrt(N-7);
	for(int i=2;i<=N-7;i++){
		if(!vis[i]){
			pr[++tot]=i,id[i]=tot;
			if(i<=V)pnum=tot;
			if(i<=V)for(int j=i*i;j<=N-7;j+=i)vis[j]=1;
			if(i>V)for(int j=i;j<=N-7;j+=i)mxp[j]=i;
		}
	}
}
inline void solve1(int l,int r){
	int k=r-l+1;
	for(int i=1;i<=tot&&pr[i]<=r;i++)if(r/pr[i]!=(l-1)/(pr[i]))k--;
	cout<<ksm(2,k)<<'\n';
}
inline bit get(int x){
	bit res;if(mxp[x])x/=mxp[x];
	for(int i=1;i<=tot&&pr[i]*pr[i]<=x;i++)
	while(x%pr[i]==0)res.flip(i),x/=pr[i];
	if(x>1)res.flip(id[x]);
	return res;
}
inline bool comp(cs int&a,cs int&b){
	return mxp[a]<mxp[b];
}
inline void insert(int x){
	if(siz==pnum)return Mul(ans,2);
	bit res=get(x)^now;
	if(res.none())return Mul(ans,2);
	for(int i=pnum;i;i--){
		if(res[i]){
			if(bas[i][i]){
				if(!(bas[i]^res).any())return Mul(ans,2);
				res^=bas[i];
			}
			else{bas[i]=res,siz++;return;}
		}
	}
}
int main(){
	init();
	int T=read();
	while(T--){
		int l=read(),r=read();
		n=0,siz=0;ans=1;
		if(r-l>=6600){solve1(l,r);continue;}
		memset(bas,0,sizeof(bas)),now.reset();	
		for(int i=l;i<=r;i++)q[++n]=i;
		sort(q+1,q+n+1,comp);
		for(int i=1;i<=n;i++){
			int x=q[i];
			if(i>1&&mxp[x]!=mxp[q[i-1]]){now=get(x);continue;}
			else insert(x);
		}
		cout<<ans<<'\n';
	}
}
posted @ 2019-08-03 17:32  Stargazer_cykoi  阅读(137)  评论(0编辑  收藏  举报