zoukankan      html  css  js  c++  java
  • 【LOJ #2978】【PKUSCH 2017】—杜老师(线性基+Bitset+结论题)

    传送门


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

    所以这道题就是:

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

    考虑由于大于nsqrt n的质因子只有11
    所以直接按最大质因子分组后需要考虑的数就只有rsqrt 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)<<'
    ';
    }
    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<<'
    ';
    	}
    }
    
  • 相关阅读:
    Cooperate with Myself
    A brief introduction of myself
    计算1+11+111+1111+........
    Jav实现F(n)=F(n-1)+F(n-2)+.....+F(1)+1
    查找二维数组中是否有符合的目标值
    排序算法
    时间复杂度
    Java代码实现单例模式
    查找一个字符串中重复出现字符的个数
    null,“”,empty的区别
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328702.html
Copyright © 2011-2022 走看看