码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-07-27 13:41:20      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:div   nbsp   部分   long   set   计算   不能   define   思路   

题意:给你一个数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 }

 

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

标签:div   nbsp   部分   long   set   计算   不能   define   思路   

原文地址:http://www.cnblogs.com/SunQi-lvbu/p/7244212.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!