THUSC2017

巧克力

LOJ

杜老师

LOJ
我们知道完全平方数的质因子个数都是偶数。
假如我们把每个数用一个记录它的质因子的个数奇偶性的bitset来表示,那么这题就变成了问\([L,R]\)内有多少个子集满足它们的bitset异或起来为\(0\)
假如我们把这些元素一个个插入线性基,那么答案就是\(2^{R-L+1-n}\)。(\(n\)为线性基的元素个数)
那么我们考虑如何快速求出这个\(n\)
找题解可以发现,如果\(R-L>6660\)(这里写的是\(6000\)),那么这个区间内的每一个出现的质数的线性基都会被插入线性基,那么我们可以直接扫一遍计算。
否则我们从\([L,R]\)枚举每个元素,计算出它们所对应的bitset,然后插入线性基即可。
注意到对于在\([L,R]\)范围内的所有数,\(>\sqrt R\)的质因子最多只有一个。
所以我们可以只要筛出\(\sqrt R\)以内的质因子,剩下的那个单独用数组判断一下之前有没有出现过这个质因数,如果没有那么这也是线性基的一个元素(但是我们不用插入而是记录在这里),如果有那么直接异或上记录的那个元素然后插入线性基。这个方法的正确性是显然的。
复杂度大概\(O(6000T\sqrt{10000000})\),不过跑起来飞快。

#include<bits/stdc++.h>
using namespace std;
const int N=500,S=6007,M=10000007,P=998244353;
int read(){int x;scanf("%d",&x);return x;}
int mul(int a,int b){return 1ll*a*b%P;}
int power(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
int id[M],pr[700007],tot,L,R,n,vis[M],stk[S],top;
bitset<N>a[N],t[S];
void init(int lim)
{
    for(int i=2,j;i<=lim;++i)
    {
    if(!id[i]) pr[++tot]=i,id[i]=tot;
    for(j=1;j<=tot&&i*pr[j]<=lim;++j)
    {
        id[i*pr[j]]=j;
        if(!(i%pr[j])) break;
    }
    }
}
void insert(bitset<N>x)
{
    for(int i=499;~i;--i)
    if(x[i])
    {
        if(a[i][i]) x^=a[i];
        else {a[i]=x,++n;break;}
    }
}
void solve()
{
    L=read(),R=read(),n=top=0;
    if(R-L>=6000)
    {
    for(int i=1;pr[i]<=R;++i) if(R/pr[i]>(L-1)/pr[i]) ++n;
    return (void)(printf("%d\n",power(2,R-L+1-n)));
    }
    for(int i=0;i<500;++i) a[i].reset();
    for(int i=L,x,p;i<=R;++i)
    {
    t[p=i-L+1].reset();
    for(x=i;x^1&&id[x]<500;x/=pr[id[x]]) t[p].flip(id[x]);
    if(x==1) insert(t[p]);
    else if(!vis[x]) vis[x]=p,++n,stk[++top]=x;
    else t[p]^=t[vis[x]],insert(t[p]);
    }
    for(int i=1;i<=top;++i) vis[stk[i]]=0;
    printf("%d\n",power(2,R-L+1-n));
}
int main()
{
    init(10000000);
    for(int T=read();T;--T) solve();
}

换桌

LOJ

大魔法师

LOJ

如果奇迹有颜色

LOJ

宇宙广播

LOJ

猜你喜欢

转载自www.cnblogs.com/cjoierShiina-Mashiro/p/12022947.html