zoukankan      html  css  js  c++  java
  • BZOJ4652: [Noi2016]循环之美(莫比乌斯反演,杜教筛)

    Description

    牛牛是一个热爱算法设计的高中生。在他设计的算法中,常常会使用带小数的数进行计算。牛牛认为,如果在 k 
    进制下,一个数的小数部分是纯循环的,那么它就是美的。现在,牛牛想知道:对于已知的十进制数 n 和 m,在 
    kk 进制下,有多少个数值上互不相等的纯循环小数,可以用分数 xy 表示,其中 1≤x≤n,1≤y≤m,且 x,y是整数
    。一个数是纯循环的,当且仅当其可以写成以下形式:a.c1˙c2c3…cp-1cp˙其中,a 是一个整数,p≥1;对于 1
    ≤i≤p,ci是 kk 进制下的一位数字。例如,在十进制下,0.45454545……=0.4˙5˙是纯循环的,它可以用 5/11
    、10/22 等分数表示;在十进制下,0.1666666……=0.16˙则不是纯循环的,它可以用 1/6 等分数表示。需要特
    别注意的是,我们认为一个整数是纯循环的,因为它的小数部分可以表示成 0 的循环或是 k?1 的循环;而一个小
    数部分非 0 的有限小数不是纯循环的。

    Input

    只有一行,包含三个十进制数N,M,K意义如题所述,保证 1≤n≤10^9,1≤m≤10^9,2≤k≤2000

    Output

    一行一个整数,表示满足条件的美的数的个数。

    Sample Input

    2 6 10

    Sample Output

    4
    explanation
    满足条件的数分别是:
    1/1=1.0000……
    1/3=0.3333……
    2/1=2.0000……
    2/3=0.6666……
    1/1 和 2/2 虽然都是纯循环小数,但因为它们相等,因此只计数一次;同样,1/3 和 2/6 也只计数一次。

    解题思路:

    一个喜闻乐见的性质,只要x/y中y与k互质就好了。

    所以这道题就是:

    $sum_{i=1}^{N}sum_{j=1}^{M}epsilon(gcd(i,j))epsilon (gcd(j, k))$

    $sum_{j=1}^{M}epsilon(gcd(j,k))sum_{i=1}^{N}epsilon(gcd(i,j))$

    $sum_{j=1}^{M}epsilon(gcd(j,k))sum_{i=1}^{N}sum_{d|gcd(i,j)}mu(d)$

    $sum_{j=1}^{M}epsilon(gcd(j,k))sum_{d=1}^{min(N,M)}mu(d)sum_{d|i}^{N}1$

    $sum_{j=1}^{M}epsilon(gcd(j,k))sum_{d=1}^{min(N,M)}mu(d)left lfloor frac{N}{d} ight floor$

    ${sum_{d=1}^{min(N,M)}epsilon(gcd(d,k))mu(d)left lfloor frac{N}{d} ight floor} sum_{i=1}^{left lfloor frac{M}{d} ight floor}epsilon(gcd(i,k))$

    莫比乌斯到这里结束,现在你可以获得84分,接下来是真正的烧脑环节。

    我讲的不好,可以看这位巨佬

    总之,将后面那个预处理出来。

    再二元递归求解整体。

    代码:

      1 #include<map>
      2 #include<cstdio>
      3 #include<algorithm>
      4 typedef long long lnt;
      5 const int N=1000100;
      6 struct pos{lnt x,k;pos(lnt a,lnt b){x=a,k=b;}};
      7 bool operator < (pos a,pos b){if(a.x!=b.x)return a.x<b.x;return a.k<b.k;}
      8 struct Dark_map{
      9     std::map<pos,lnt>A;
     10     void insert(lnt x,lnt k,lnt v){A[pos(x,k)]=v;return ;}
     11     bool hav(lnt x,lnt k){return A.find(pos(x,k))!=A.end();}
     12     lnt val(lnt x,lnt k){return A[pos(x,k)];}
     13 }S;
     14 struct New_map{
     15     std::map<lnt,lnt>A;
     16     lnt a[N];
     17     void insert(lnt p,lnt x){if(p<N)a[p]=x;else A[p]=x;return ;}
     18     bool hav(lnt x){if(x<N)return true;return A.find(x)!=A.end();}
     19     lnt val(lnt x){if(x<N)return a[x];return A[x];}
     20 }Miu;
     21 int prime[N];
     22 int miu[N];
     23 bool vis[N];
     24 int cnt;
     25 int n,m,k;
     26 int twd[N];
     27 int lst[N];
     28 lnt f[2001];
     29 int hd[2001];
     30 lnt gcd(lnt a,lnt b){if(!b)return a;return gcd(b,a%b);}
     31 void adde(int f,int t){cnt++;twd[cnt]=t;lst[cnt]=hd[f];hd[f]=cnt;return ;}
     32 void gtp(void)
     33 {
     34     for(int i=1;i<=k;i++)f[i]=f[i-1]+(gcd(i,k)==1);
     35     for(int i=1;i<=k;i++)for(int j=i;j<=k;j+=i)adde(j,i);
     36     miu[1]=1,cnt=0;
     37     for(int i=2;i<N;i++)
     38     {
     39         if(!vis[i])
     40         {
     41             prime[++cnt]=i;
     42             miu[i]=-1;
     43         }
     44         for(int j=1;j<=cnt&&i*prime[j]<N;j++)
     45         {
     46             vis[i*prime[j]]=true;
     47             if(i%prime[j]==0)
     48             {
     49                 miu[i*prime[j]]=0;
     50                 break;
     51             }
     52             miu[i*prime[j]]=-miu[i];
     53         }
     54     }
     55     for(int i=1;i<N;i++)
     56         Miu.insert(i,Miu.val(i-1)+1ll*miu[i]);
     57     return ;
     58 }
     59 lnt F(lnt x)
     60 {
     61     return (x/k)*f[k]+f[x%k];
     62 }
     63 lnt MIU(lnt x)
     64 {
     65     if(Miu.hav(x))
     66         return Miu.val(x);
     67     lnt tmp=0;
     68     for(int i=2,j;i<=x;i=j+1)
     69     {
     70         j=x/(x/i);
     71         tmp+=1ll*(j-i+1)*MIU(x/i);
     72     }
     73     tmp=1-tmp;
     74     Miu.insert(x,tmp);
     75     return tmp;
     76 }
     77 lnt SUM(lnt Nn,lnt Kk)
     78 {
     79     if(S.hav(Nn,Kk))
     80         return S.val(Nn,Kk);
     81     lnt tmp=0;
     82     if(Nn<1);
     83     else if(Kk==1)
     84         tmp=MIU(Nn);
     85     else{
     86         for(int I=hd[Kk];I;I=lst[I])
     87         {
     88             int x=twd[I];
     89             lnt TMP=miu[x];
     90             if(!TMP)
     91                 continue;
     92             tmp+=SUM(Nn/x,x);
     93         }
     94     }
     95     S.insert(Nn,Kk,tmp);
     96     return tmp;
     97 }
     98 int main()
     99 {
    100     scanf("%d%d%d",&n,&m,&k);
    101     gtp();
    102     lnt ans=0;
    103     for(int i=1,j;i<=n&&i<=m;i=j+1)
    104     {
    105         j=std::min(n/(n/i),m/(m/i));
    106         ans+=(SUM(j,k)-SUM(i-1,k))*(lnt)(n/i)*F(m/i);
    107     }
    108     printf("%lld
    ",ans);
    109     return 0;
    110 }
  • 相关阅读:
    Docker容器启动时初始化Mysql数据库
    使用Buildpacks高效构建Docker镜像
    Mybatis 强大的结果集映射器resultMap
    Java 集合排序策略接口 Comparator
    Spring MVC 函数式编程进阶
    换一种方式编写 Spring MVC 接口
    【asp.net core 系列】6 实战之 一个项目的完整结构
    【asp.net core 系列】5 布局页和静态资源
    【asp.net core 系列】4. 更高更强的路由
    【Java Spring Cloud 实战之路】- 使用Nacos和网关中心的创建
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10162443.html
Copyright © 2011-2022 走看看