zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    hdu 1593 find a way to escape
    bzoj4561: [JLoi2016]圆的异或并
    hdu 3511 Prison Break
    hdu 5299 Circles Game
    ORA-15025: could not open disk "/dev/asm***"--转载
    修改目的端trail文件的最大大小--转载
    MYSQL PERFORMANCE_SCHEMA HINTS
    Oracle 收缩表大小 Oracle Shrink Table --转载
    InnoDB: Error number 24 means ‘Too many open files’.--转载
    使用asmcmdcp命令把datafile从文件系统移动(move)到asm磁盘组中 针对11gR2
  • 原文地址:https://www.cnblogs.com/Narh/p/10839391.html
Copyright © 2011-2022 走看看