zoukankan      html  css  js  c++  java
  • zgg与占卜师

    题目大意

     
    给出一个整数$n$的标准分解,求经过多少次$n=phi(n)$操作后,可以使$n=1$。标准分解式中,质数$P le 10^5$,次数$t le 10^9$。多组数据,最后再输出所有答案中的最大值。
     

    分析

     
    欧拉函数的公式:$phi(n)=sum P_i^{t_i-1}cdot(P_i-1)$,其中$P_i$、$t_i$为标准分解后得到的质因数和对应的次数。
     
    根据欧拉函数的公式可以发现,每次进行$n=phi(n)$的操作后,所有的质数$P$的次数都减去$1$,然后又多出来$(P-1)$的质因数。而一旦$n$变为$1$,仅当质因数$P$仅有$2$。
     
    因为所有的质因数结果不断地操作,最后都要通过$2$这个媒介再变为$1$,且这个过程中$2$的个数必然大于$0$(因为每次必有一个$P$变为$P-1$,而当$P$不为$2$时,$P-1$必然包含$2$这个因子)。
     
    由于其它质因数变化是和$2$的变化同时进行的,且$2$的变化贯穿这个过程(若原本的$n$包含$2$这个质因子时),而每次操作$2$的次数减一,所以将其它的质数都拆解成2,最后$2$的次数便是答案。
     
    若原本的$n$不包含$2$这个质因子,则第一次操作时$2$的次数不减少(都是$0$),而后面的操作与前面一样,故答案为$2$的次数加一。
     

    实现

     
    根据分析,可以知道最重要的东西是一个数可以拆解为多少个$2$,对此我们假设要拆解的数为$x$,对$x$进行分类讨论。
     
    • 当$x$为偶数时,$x$可拆解出的$2$的个数为$frac{x}{2}$拆解出的$2$的个数加一。
     
    • 当$x$为奇数时,$x$中不含有$2$这个质因子,所以$phi(x)$相对$x$而言拆解出的$2$的个数不减少,所以$x$可拆解出的$2$的个数为$phi(x)$拆解出的$2$的个数。
     
    对于任意一个数$x$,都由小于$x$的数贡献答案,所以递推求就好了。
     
    代码:
     1 #include <cstdio>
     2 
     3 int f[100010], phi[100010], two[100010];
     4 int test, n, a, b, flag;
     5 long long ans, maxans;
     6 
     7 int main()
     8 {
     9     for (int i = 2; i < 100000; i++)
    10     {
    11         if (f[i]) continue;
    12         phi[i] = i - 1;
    13         for (int j = i + i; j < 100000; j += i)
    14         {
    15             f[j] = 1;
    16             if (phi[j] == 0) phi[j] = j;
    17             phi[j] = phi[j] / i * (i - 1);
    18         }
    19     }
    20     for (int i = 2; i < 100000; i++)
    21     {
    22         if (i % 2 == 0) two[i] = two[i / 2] + 1;
    23         else two[i] = two[phi[i]];
    24     }
    25     scanf("%d", &test);
    26     maxans = 0;
    27     while (test--)
    28     {
    29         scanf("%d", &n);
    30         ans = flag = 0;
    31         while (n--)
    32         {
    33             scanf("%d %d", &a, &b);
    34             if (a == 2) flag = 1;
    35             ans += (long long) two[a] * b;
    36         }
    37         ans = ans - flag + 1;
    38         printf("%lld
    ", ans);
    39         if (ans > maxans) maxans = ans;
    40     }
    41     printf("%lld", maxans);
    42 }
  • 相关阅读:
    node-sass 安装失败
    js中复制功能总结
    设置NODE_ENV=test环境变量
    js eslint语法规范错误提示代码
    npm安装node包时怎么显示安装进度
    前端面试题总结三
    5种方式将数字转成千分位
    前端面试题总结二(js原型继承)
    前端面试题总结一(js变量和函数声明提前相关)
    1109 Group Photo (25分)
  • 原文地址:https://www.cnblogs.com/lightning34/p/4600863.html
Copyright © 2011-2022 走看看