• UVA 11426 (欧拉函数&&递推)


    题意:给你一个数N,求N以内和N的最大公约数的和

    解题思路:

    一开始直接想暴力做,4000000的数据量肯定超时。之后学习了一些新的操作。

    题目中所要我们求的是N内gcd之和,设s[n]=s[n-1]+gcd(1,n)+gcd(2,n)+gcd(3,n)+gcd(4,n).......

    再设f[n]=gcd(1,n)+gcd(2,n)+gcd(3,n)+gcd(4,n).......;

    思考一下,假设gcd(x,n)=ans,ans便是x和n的最大公约数,那么有几个ans我们将某ans的个数sum(num*ans)是不是就是当前f[n]的值;

    那么某个ans的个数num我们该怎么求???

    gcd(x,n)=ans;那么gcd(x/ans,n/ans)就是1;就是说x/ans和n/ans是互素的,那么求n以内和n互素的数的个数我们怎么办???就用欧拉函数phi;

    其个数就是phi[n/ans];

    然后,,,,你以为求这点就做完了是吗??玩笑,,,;

    你可以直接打出4000 000欧拉表,那么我们该怎么遍历赋值f[n];f[n]=num*ans;我们遍历n在遍历ans么??这个不现实,在当前这个n中会有部分ans白白计算

    所以我们最好的办法就是先行枚举ans,我们知道,当前ans所对应的n一定是ans的倍数,所以我们遍历n极为方便,只需要令n=2*ans,3*ans,4*ans,5*ans......

    这里有个点就是n不能是ans,所以我们第二重循环里就应该从2*ans开始;这个地方一会在代码中点出;

    具体就是这么多;

    AC代码

     1 #include<stack>
     2 #include<queue>
     3 #include<cmath>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<iostream>
     7 #include<algorithm>
     8 
     9 using namespace std;
    10 
    11 #define INF 0x3f3f3f3f
    12 typedef long long ll;
    13 const ll maxn = 4000005;
    14 ll n;
    15 
    16 ll euler[maxn];
    17 ll fun_[maxn];
    18 
    19 void euler_(ll maxn)
    20 {
    21     for (int i=1;i<=maxn;i++)
    22     {
    23         euler[i]=i;
    24     }
    25     for (int i=2;i<maxn;i++)
    26     {
    27         if (euler[i]==i)
    28         {
    29             for (int j=i;j<maxn;j+=i)
    30             {
    31                 euler[j]=euler[j]/i*(i-1);
    32                // cout<<euler[j]<<endl;
    33             }
    34         }
    35     }
    36 }
    37 
    38 ll s[maxn];
    39 
    40 
    41 int main()
    42 {
    43     euler_(maxn);
    44     //memset(fun_,0,sizeof(fun_));
    45     for (int i=1;i<=maxn;i++)
    46     {
    47         for (int j=i+i;j<=maxn;j+=i)
    48         {
    49             //cout<<i<<" "<<n/i<<" "<<euler[n/i]<<endl;
    50 
    51             fun_[j]+=i*euler[j/i];
    52             //cout<<fun_[j]<<endl;
    53         }
    54     }
    55     s[1]=0;
    56 
    57     for (int i=2;i<=maxn;i++)
    58     {
    59         s[i]=s[i-1]+fun_[i];
    60         //cout<<i<<" "<<s[i]<<endl;
    61     }//cout<<"***********"<<endl;
    62     while (cin>>n&&n)
    63     {
    64         //cout<<n<<endl;
    65         cout<<s[n]<<endl;
    66     }
    67 }
  • 相关阅读:
    Apache(文章测试)
    这是一篇Markdown手册
    Linux MySQL 8.0 忘记密码
    composer 自动加载源码解析
    Linux 连接 Internet
    PHP namespace、abstract、interface、trait使用介绍
    网络基础知识
    CentOS7安装Nginx、MySQL、PHP
    局域网内使用ssh连接两台计算机总结
    整数和浮点数的表示方法
  • 原文地址:https://www.cnblogs.com/SunQi-lvbu/p/7244212.html
Copyright © 2020-2023  润新知