哈哈,【】nm$l
Schwarzkopf_Henkal · · 题解
这是道大 nb 题,就在我开始写的时候这还是道紫题,写着写着就变成黑的了。
首先,我们观察题面,发现是求乘积为完全平方数的子集的方案数。然后我们有一个套路,如果这个子集内的所有数的质因数分解结果相加全部都是偶数,那么这一定是个完全平方数,而这个奇偶性的合并跟异或是等价的。然后想到线性基,问题等价于求使得线性基所有位为
也就是说,我们可以处理 bitset 做少一个
但是根据质因数分解的性质,我们知道,对于一个数,大于 unordered_map<int,bitset<455> > 来专门存储这部分的线性基,插入单个数的复杂度就变成了
我们发现,相比于线性基的最大大小,可能的区间长度实际上非常大,也就是说,线性基非常被填满。然后我们从裤裆里掏出一个结论,当区间长度大于一个特定的值的时候,一定有一个方案使得每一个出现过的质因数都能够在线性基里面占据一个单独的位置。此处的出现,指的是作为某个数的因数出现。
于是我们可以处理出
隐蔽的坑:我发过一个帖子,如果踩进那个坑里将会只剩下
#include<bits/stdc++.h>
using namespace std;
const long long Mod=998244353;
long long T,L,R,mk[10000005],pr1[114514],pr2[665000],t1,t2,S;
bitset<455>a[455];
unordered_map<int,bitset<455>>mts;
void insert(int u){
bitset<455>v;
for(int i=1;i<=t1&&u!=1;i++){
while(u%pr1[i]==0){
u/=pr1[i];
v[i]=!v[i];
}
}
if(u!=1){
if(!mts.count(u)){
mts[u]=v;
S++;
return;
}
v^=mts[u];
}
for(int i=t1;i>=1;i--)
if(v[i]){
if(!a[i].any()){
a[i]=v;
S++;
return;
}
v^=a[i];
}
}
void clear(){
S=0;
mts.clear();
for(int i=1;i<=t1;i++)
a[i].reset();
}
long long Pow(long long u,long long v){
long long res=1;
while(v){
if(v&1)
res=res*u%Mod;
u=u*u%Mod;
v>>=1;
}
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
for(int i=2;i<=10000000;i++)
if(!mk[i]){
if(i<=3200)
pr1[++t1]=i;
pr2[++t2]=i;
if(1ll*i*i<=10000000)
for(int j=i*i;j<=10000000;j+=i)
mk[j]=1;
}
cin>>T;
while(T--){
clear();
cin>>L>>R;
if(R-L+1<=7000){
for(int i=L;i<=R;i++)
insert(i);
}else {
for(int i=1;i<=t2&&pr2[i]<=R;i++)
if(R/pr2[i]!=(L-1)/pr2[i])
S++;
}
cout<<Pow(2,R-L+1-S)<<'\n';
}
}/*
首先,预处理根号以内的质数,
然后bitset预处理谔谔。
不过,这样不会超时吗?
对啊,它不是要求O(n)吗
看起来是个大nb题但是为什么这个只有紫
好棒/se有50分
*/