【LOJ #2978】【PKUSCH 2017】—杜老师(线性基+Bitset+结论题)
完全平方数说白了就是每个质因子出现了偶数次
所以这道题就是:
给你个集合
问有多少种集合选的方案使得集合异或为空
考虑由于大于的质因子只有个
所以直接按最大质因子分组后需要考虑的数就只有以内的
筛一下就只有个左右
所以把每个质因子奇偶看做二进制位
就相当于选出数使得异或和为0
就相当于构建一个线性基,答案就是
可以用优化一下
复杂度
而题解说如果在大概以上的时候线性基是满的
所以这时候答案就是
然后就跑的飞快了
#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';
}
}