zoukankan      html  css  js  c++  java
  • 【BZOJ2749】【HAOI2012】外星人[欧拉函数]

    外星人

    Time Limit: 3 Sec  Memory Limit: 128 MB
    [Submit][Status][Discuss]

    Description

      

    Input

       

    Output

      输出test行,每行一个整数,表示答案。

    Sample Input

      1
      2
      2 2
      3 1

    Sample Output

      3
      

    HINT

      Test<=50 Pi<=10^5,1<=Q1<=10^9

    Main idea

      给定一个数,用Πp[i]^q[i](p<=10^5,q<=10^9)的形式表示,问最少需要对这个数字x进行几次x=Φ(x)操作使得x=1。

    Solution

      这显然是一道数论题。
      首先想到了只有Φ(2)=1,所以最后答案必然需要转成带2的形式,我们先考虑一个数字,由欧拉函数的推导公式Φ(Πp[i]^q[i])=Π(p[i]-1)*p[i]^(q[i]-1)可以发现每次求Φ会消去一个质因数2,并且产生若干个2(产生的2是有上限的)。
      这句话是什么意思呢?
      我们举个例子:讨论一个偶数180=2^2 * 3^2 * 5,Φ(180)=2^1 * (3-1)*3 * (5-1)=48,这里产生了3个2,消去了1个2。
      所以我们只要求出产生了几个2即可(由于除了Φ(2)以外的数都是偶数,所以任意奇数只要经过一遍求Φ就可以变为偶数来处理,次数+1),因为每次只能消去一个1,所以答案就应该是这个数分解出的2的个数。
      知道欧拉函数是一个积性函数,并且我们现在求的显然是一个完全积性函数,由于这个性质,求分解出几个2可以使用线性筛来实现,对于每一项p[i]^q[i]分解出的个数就是(p[i]分解出的个数*q[i]),答案就是Σ(每一项分解出的个数)

    Code

     1 #include<iostream>  
     2 #include<algorithm>  
     3 #include<cstdio>  
     4 #include<cstring>  
     5 #include<cstdlib>  
     6 #include<cmath>
     7 #include<queue>
     8 using namespace std;  
     9         
    10 const int ONE=100001;
    11  
    12 int T;
    13 int f[ONE],p[ONE],tot,phi[ONE];
    14 int x,y,m,PD;
    15 long long Ans;
    16  
    17 int get()
    18 {
    19         int res,Q=1;    char c;
    20         while( (c=getchar())<48 || c>57)
    21         if(c=='-')Q=-1;
    22         if(Q) res=c-48; 
    23         while((c=getchar())>=48 && c<=57) 
    24         res=res*10+c-48; 
    25         return res*Q; 
    26 }
    27  
    28 void Get_f(int n)
    29 {
    30         phi[1]=1;
    31         for(int i=2;i<=n;i++)
    32         {
    33             if(!f[i]) 
    34             {   
    35                 p[++tot]=i;
    36                 phi[i]=phi[i-1];
    37             }
    38              
    39             for(int j=1;j<=tot;j++)
    40             {
    41                 if(i*p[j]>n) break;
    42                 f[i*p[j]]=1;
    43                 phi[i*p[j]]=phi[i]+phi[p[j]];
    44                 if(i%p[j]==0) break;
    45             }
    46         }
    47 }
    48  
    49 int main()
    50 {
    51         Get_f(ONE-1);
    52         T=get();
    53         while(T--)
    54         {
    55             m=get();
    56             Ans=PD=0; 
    57             for(int i=1;i<=m;i++)
    58             {
    59                 x=get();    y=get(); 
    60                 Ans+=(long long)phi[x]*y;
    61                 if(!PD && x==2) PD=1;
    62             }
    63             printf("%lld
    ",Ans+(!PD));
    64         }
    65 }
    View Code
  • 相关阅读:
    (创建型模式)Abstract Factory——抽象工厂模式
    (结构型模式)Composite——组合模式
    (行为模式)Command——命令模式
    (创建型模式)Singleton——单例模式
    Windows的Notepad++的插件
    Ubuntu的软件源更新常见问题及解决
    The following signatures were invalid: BADSIG 40976EAF437D05B5 Ubuntu Archive Automatic Signing Key
    Ubuntu安装ImageMagick
    常见误操作之警惕
    Rails3.2.x new project启动错误:Could not find a JavaScript runtime.
  • 原文地址:https://www.cnblogs.com/BearChild/p/6441418.html
Copyright © 2011-2022 走看看