# LOJ #2978「THUSCH 2017」杜老师

LOJ #2978

### 题意

$T$次询问，每次询问$L,R$，问有多少种选取区间中数的方案使得选出的数的积为完全平方数

$T \leq 100,R \leq 10^7 \sum\limits R-L \leq 6·10^7$

### 代码

去掉Solve就是暴力

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<bitset>
#define p 998244353
#define file(x)freopen(x".in","r",stdin);freopen(x".out","w",stdout)
#define rt register int
#define l putchar('\n')
#define ll long long
using namespace std;
ll x=0;char zf=1;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-1,ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*zf;
}
void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans,val=10000000;
bool pri[10000010];int ss[4010],id[4010],lp[10000010],zs[1000010],tot;
bitset<449>a[449];
int q[10000010],sl;
bitset<449>make(int x){
bitset<449>A;
if(lp[x])x/=lp[x];
for(rt i=1;ss[i]*ss[i]<=x&&i<=cnt;i++)while(x%ss[i]==0)
A.flip(i),x/=ss[i];
if(x>1)A.flip(id[x]);
return A;
}
vector<int>jw[5000010];
void solve(int L,int R){
int gs=R-L+1;
for(rt i=1;i<=tot&&zs[i]<=R;i++)if(R/zs[i]!=(L-1)/zs[i])gs--;
int ans=1;
for(rt x=2,i=gs;i;i>>=1,x=1ll*x*x%p)if(i&1)
ans=1ll*ans*x%p;writeln(ans);
}
int main(){
n=r;if(n<=10)val=1000000;
const int v=sqrt(val);
for(rt i=2;i<=val;i++)if(!pri[i]){
if(i<=v)ss[++cnt]=i,id[i]=cnt;
zs[++tot]=i;
if(i<=v)for(rt j=i*i;j<=val;j+=i)pri[j]=1;
if(i>v)for(rt j=i;j<=val;j+=i)lp[j]=i;
}
bitset<449>now;
while(n--){
memset(a,0,sizeof(a));
int L=r,R=r,ans=1;int len=0;
if(R-L>7000){
solve(L,R);
continue;
}
for(rt i=L;i<=R;i++)if(lp[i]<=5000000)jw[lp[i]].push_back(i);
for(rt i=L;i<=R;i++)if(lp[i]<=5000000){
for(rt j=0;j<jw[lp[i]].size();j++)q[++len]=jw[lp[i]][j];
jw[lp[i]].clear();
}
sl=0;now&=0;
for(rt i=1;i<=len;i++){
const int v=q[i];
if(lp[v]!=lp[q[i-1]]&&i>1)now=make(v);
else {
if(sl==cnt){ans=1ll*ans*2%p;continue;}
bitset<449>g=make(v)^now;
if(g.count()==0){ans=1ll*ans*2%p;continue;}
for(rt j=448;j>=0;j--)if(g[j]){
if(a[j][j]){
if(g==a[j]){ans=1ll*ans*2%p;break;}
g^=a[j];
}
else {a[j]=g;sl++;break;}
}
}
}
writeln(ans);
}
return 0;
}

posted @ 2019-01-18 08:02  Kananix  阅读(598)  评论(0编辑  收藏