• LOJ 2978 「THUSCH 2017」杜老师——bitset+线性基+结论


    题目:https://loj.ac/problem/2978

    题解:https://www.cnblogs.com/Paul-Guderian/p/10248782.html

    第 i 个数的 bitset 的第 j 位表示 i 是否含有奇数个 “第 j 个质数” 。

    想到用 bitset ,就开始考虑怎样 DP ……

    其实是求选一些数,使得它们的 bitset 异或和为 0 。所以求线性基,答案就是 2R-L+1-线性基大小

    然后考虑根号分治。

    大于 ( sqrt{n} ) 的质数,每个数最多含有其一次方。所以一个大于 ( sqrt{n} ) 的质数一旦出现,线性基里就一定有它。

    所以对小于 ( sqrt{n} ) 的约 500 个质数做线性基。

    找出每个数的最大质因子,如果是大于 ( sqrt{n} ) 的,直接 dec++(dec 是记录的线性基大小);如果该质因子已经出现过,就把该数的剩余部分异或掉该质因子第一次出现的那个数的剩余部分,然后尝试加入线性基。

    似乎区间长度 >= 6000 的话,一个质因子一旦出现就一定会在线性基里。判断小于 ( sqrt{n} ) 的质因子是否出现,只需看 (L-1)/pri < R/pri 。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<bitset>
    #include<cmath>
    #define ll long long
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    const int N=505,M=1e7+5,mod=998244353;
    int upt(int x){while(x>=mod)x-=mod;while(x<0)x+=mod;return x;}
    
    int L,R,lm,pri[M],cnt,mxd[M],mnd[M],dy[M];
    int q[6005],dfn[M],bin[M];bool vis[M];
    bitset<N> bs[N],nw,pr;
    bool cmp(int u,int v){return mxd[u]<mxd[v];}
    void init()
    {
      int n=1e7;lm=sqrt(n); ll d;
      for(int i=2;i<=n;i++)
        {
          if(!vis[i]){ pri[++cnt]=i;dy[i]=cnt;mxd[i]=mnd[i]=i;}
          for(int j=1;j<=cnt&&(d=(ll)i*pri[j])<=n;j++)
        {
          vis[d]=1; mnd[d]=pri[j]; mxd[d]=mxd[i];
          if(i%pri[j]==0)break;
        }
        }
      for(int i=1;i<=cnt;i++)
        if(pri[i]>lm){cnt=i-1;break;}
      bin[0]=1;for(int i=1;i<=n;i++)bin[i]=upt(bin[i-1]<<1);
    }
    void get(int x)
    {
      if(mxd[x]>lm)x/=mxd[x]; nw.reset();
      while(x>1)
        {
          int t=0,d=mnd[x];
          while(mnd[x]==d)x/=d,t++;
          if(t&1)nw.set(dy[d]-1);
        }
    }
    int Ins()
    {
      for(int i=0;i<cnt;i++)
        if(nw[i])
          {
        if(bs[i][i])nw^=bs[i];
        else {bs[i]=nw;return 1;}
          }
      return 0;
    }
    void solve1()
    {
      int tot=0; for(int i=L;i<=R;i++)q[++tot]=i;
      sort(q+1,q+tot+1,cmp);
      for(int i=0;i<cnt;i++)bs[i].reset();
      int dec=0,d2=0;
      for(int i=1,cr;i<=tot;i++)
        {
          cr=q[i]; get(cr);
          if(mxd[cr]<=lm)dec+=Ins();
          else if(mxd[cr]!=mxd[q[i-1]])
        { d2++; pr=nw;}
          else
        { nw^=pr; dec+=Ins();}
          if(dec==cnt+1)break;//can't cal d2!!!
        }
      printf("%d
    ",bin[tot-dec-d2]);
    }
    void solve2(int tim)
    {
      int dec=0;
      for(int i=L;i<=R;i++)
        {
          int cr=mxd[i];
          if(cr>lm&&dfn[cr]!=tim)dfn[cr]=tim,dec++;
        }
      for(int i=1;i<=cnt;i++)
        if((L-1)/pri[i]<R/pri[i])dec++;
      printf("%d
    ",bin[R-L+1-dec]);
    }
    int main()
    {
      init(); int T=rdn();
      while(T--)
        {
          L=rdn(),R=rdn();
          if(R-L+1>=6000)solve2(T+1);
          else solve1();
        }
      return 0;
    }
  • 相关阅读:
    2022.05.31软件更新公告
    为什么不网购方便面
    js localStorage
    uniapp上拉加载更多功能的简单实现
    Centos 系统 软raid 0 实现
    使用vscode调试ros
    wget 命令用法
    是否应该提前还房贷
    mybatis generator 自动生成的拼装sql分析
    动态样式+模板字符串
  • 原文地址:https://www.cnblogs.com/Narh/p/10839391.html
Copyright © 2020-2023  润新知