zoukankan      html  css  js  c++  java
  • 【BZOJ 4652】【NOI 2016】循环之美

    题目连接:

      传送

    题解:

      真是一道好题……

    一:

      一个分数$frac{x}{y}$完全循环当其第一次出现时,当且仅当y与k互质,x与y互质,且y不等于1。

      整数情况下y一定为1,即也满足以上判断。

      推导:

        方法一:打表找规律= =

        方法二:x与y互质去重= =,设循环次数为l,则对于循环节第一次循环前剩余$xmod y$,第二次循环前剩余$xk^lmod y$,若其为循环则满足:,由x与y互质可知存在x对y的逆元,所以:

            

    由贝祖定理可知,k与y互质。

    二、反演:

              

      考虑d前面时间复杂度为$O(sqrt{k}ln k)$,后边分块时间复杂度$O(sqrt n)$

      考虑如何得到$S(n,sg)=sum_{i=1}^n mu(isg)$。

      1.当$mu(sg)==0$时,上式为0;

      2.设p为sg质因数,则有$S(n,sg)=sum_{i=1}^nmu(i)([p|i]-1)$,故$S(n,sg)=S(n/p,sg)-S(n,sg/p)$。

      故求一次$S(n,sg)$的时间复杂度约为$(O(2^{k的质因子个数}))$。

    三、时间复杂度

      $O(sqrt{nk}ln k)$  

    代码:

     1 #include "bits/stdc++.h"
     2 
     3 using namespace std;
     4 
     5 const int N=2e7+5;
     6 
     7 int prim[N],num,miu[N],pre[N];
     8 bool vis[N];
     9 
    10 inline void init(){
    11     miu[1]=1;
    12     pre[1]=1;
    13     register int i,j;
    14     for( i=2;i<N;++i){
    15         if(!vis[i])
    16             prim[++num]=i,miu[i]=-1;
    17         for( j=1;prim[j]*i<N;++j){
    18             vis[i*prim[j]]=true;
    19             if(i%prim[j])   {
    20                 miu[i*prim[j]]=-miu[i];
    21             }else{
    22                 miu[i*prim[j]]=0;break;
    23             }
    24         }
    25         pre[i]+=pre[i-1]+miu[i];
    26     }
    27 }
    28 
    29 int n,m,k,wr[N],cnt;
    30 int fac[2005][10005];
    31 vector<int> factor[2005];
    32 
    33 map<int,int> ss;
    34 
    35 inline int Get_miu(int x){
    36     if(x<N) return pre[x];
    37     if(ss.count(x)) return ss[x];
    38     int ans=1;
    39     for(int i=2,pos;i<=x;i=pos+1){
    40         pos=x/(x/i);
    41         ans-=Get_miu(x/i)*(pos-i+1);
    42     }
    43     return ss[x]=ans;
    44 }
    45 
    46 inline int get_miu(int x,int sg){    
    47     if(sg==1)return Get_miu(x);
    48     if(x<=10000) return fac[sg][x];
    49     else    {
    50         int p=wr[sg];
    51         return get_miu(x/p,sg)-get_miu(x,sg/p);
    52     }
    53 }
    54 
    55 int main(){
    56     //  freopen("1.out","r",stdin);
    57     // freopen("b1.out","w",stdout);
    58     scanf("%d%d%d",&n,&m,&k);
    59     init();
    60     for(int i=1;i<=k;++i)
    61         for(int j=1;j<=i;++j)
    62             if(i%j==0)  factor[i].push_back(j);
    63         
    64     for(int i=1;i<=2000;++i)
    65         for(int j=1;prim[j]<=i;++j) if(i%prim[j]==0)   wr[i]=prim[j];
    66     for(int i=1;i<=2000;++i)
    67         if(k%i==0)
    68         for(int j=1;j<=10000;++j)
    69             fac[i][j]=fac[i][j-1]+miu[j*i];
    70 
    71     long long ans=0,sum;
    72     register int d,pos;
    73     int last,now,nn,mm,t1,t2,t,g,s,p,q;
    74     for(int i=0;i<factor[k].size();++i){
    75         t=factor[k][i];
    76         sum=0;
    77         for( p=0;p<factor[t].size();++p){
    78              g=factor[t][p];
    79             for( q=0,s;q<factor[t/g].size();++q){
    80                 s=factor[t/g][q];
    81                 t1=s*g,t2=s*t;
    82                 nn=n/t1,mm=m/t2;
    83                 last=0,now;
    84                 if(miu[s*g]==0) continue;
    85                 for(d=1,pos;d<=min(nn,mm);d=pos+1){
    86                     pos=min(nn/(nn/d),mm/(mm/d));
    87                     now=get_miu(pos,s*g);
    88                     sum+=(now-last)*1ll*(nn/d)*(mm/d)*miu[s];
    89                     last=now;
    90                 }
    91             }
    92         }
    93         ans+=sum*miu[t];
    94     }
    95     printf("%lld
    ",ans);
    96 }

     

  • 相关阅读:
    How to create Ubuntu Image with Linaro Image Tools
    linux little tool
    Firefly-RK3288
    tensorflow 出现KeyError: 'tulips\8689672277_b289909f97_n.jpg'报错
    开发中涉及的框架与工具
    这三年被分布式坑惨了,曝光十大坑 【转载】
    C#动态编译及执行代码
    cron表达式可视化编辑页面
    AVPacket相关函数介绍
    ffmpeg 重要函数介绍
  • 原文地址:https://www.cnblogs.com/Troywar/p/8327381.html
Copyright © 2011-2022 走看看