POJ2480——Longge's problem(数论,欧拉函数d)
2016-07-20 22:21
561 查看
题目:
Longge's problem
Description
Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N.
"Oh, I know, I know!" Longge shouts! But do you know? Please solve it.
Input
Input contain several test case.
A number N per line.
Output
For each N, output ,∑gcd(i, N) 1<=i <=N, a line
Sample Input
Sample Output
大意:就是求[1,n]的整数和n的最大公约数的和
思路:肯定不能暴力。区间是[1,n],数是n,马上就想到欧拉函数。怎么联系起来?欧拉函数是求互质的数的个数。比如如果n能整除2,那么与n最大公约数为2的数的个数为区间[1,n/2]里头与n/2互质的数的个数。那么和就是phi[n/2]*2。
怎么降低复杂度呢?还是拿2举例子。n/2肯定也是n的约数,那么再加上phi[2]*n/2即可。
代码如下
#include <cmath>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
#include <string>
#include <set>
#include <cmath>
using namespace std;
typedef long long ll;
const int Max=100010;
ll p[Max];
bool is_prime[Max];
ll euler(ll n){
ll res=n,a=n;
for(int i=0;p[i]*p[i]<=a;i++){
if(a%p[i]==0){
res=res/p[i]*(p[i]-1);
while(a%p[i]==0) a/=p[i];
}
}
if(a>1) res=res/a*(a-1);
return res;
}
int main()
{
ll n;
int k=0;
for(int i=0;i<Max;i++)
is_prime[i]=true;
for(int i=2;i<Max;i++)
{
if(is_prime[i])
{
for(int j=2*i;j<Max;j+=i)
is_prime[j]=false;
p[k++]=i;
}
}
while(scanf("%lld",&n)!=EOF)
{
ll sq=(int)sqrt((double)n);
ll ans=0;
for(int i=1;i<=sq;i++)
{
if(i*i==n)
{
ans+=euler(i)*i;
}
else if(n%i==0)
{
long long s=n/i;
ans+=euler(s)*i+euler(i)*s;
}
}
printf("%lld\n",ans);
}
return 0;
}
Longge's problem
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 8050 | Accepted: 2666 |
Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N.
"Oh, I know, I know!" Longge shouts! But do you know? Please solve it.
Input
Input contain several test case.
A number N per line.
Output
For each N, output ,∑gcd(i, N) 1<=i <=N, a line
Sample Input
2 6
Sample Output
3 15
大意:就是求[1,n]的整数和n的最大公约数的和
思路:肯定不能暴力。区间是[1,n],数是n,马上就想到欧拉函数。怎么联系起来?欧拉函数是求互质的数的个数。比如如果n能整除2,那么与n最大公约数为2的数的个数为区间[1,n/2]里头与n/2互质的数的个数。那么和就是phi[n/2]*2。
怎么降低复杂度呢?还是拿2举例子。n/2肯定也是n的约数,那么再加上phi[2]*n/2即可。
代码如下
#include <cmath>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
#include <string>
#include <set>
#include <cmath>
using namespace std;
typedef long long ll;
const int Max=100010;
ll p[Max];
bool is_prime[Max];
ll euler(ll n){
ll res=n,a=n;
for(int i=0;p[i]*p[i]<=a;i++){
if(a%p[i]==0){
res=res/p[i]*(p[i]-1);
while(a%p[i]==0) a/=p[i];
}
}
if(a>1) res=res/a*(a-1);
return res;
}
int main()
{
ll n;
int k=0;
for(int i=0;i<Max;i++)
is_prime[i]=true;
for(int i=2;i<Max;i++)
{
if(is_prime[i])
{
for(int j=2*i;j<Max;j+=i)
is_prime[j]=false;
p[k++]=i;
}
}
while(scanf("%lld",&n)!=EOF)
{
ll sq=(int)sqrt((double)n);
ll ans=0;
for(int i=1;i<=sq;i++)
{
if(i*i==n)
{
ans+=euler(i)*i;
}
else if(n%i==0)
{
long long s=n/i;
ans+=euler(s)*i+euler(i)*s;
}
}
printf("%lld\n",ans);
}
return 0;
}
相关文章推荐
- 宏与可变参数
- Windows去除快捷箭头
- HTTP协议
- 关于time.h头文件
- LeetCode - 173. Binary Search Tree Iterator
- 模板方法模式(Template Method)
- 图的概念
- 重学 Statistics,Cha7 Sampling and Sampling Distribution
- 刻录DVD_目录
- DocStrings
- web.xml执行顺序
- HDU 5724 (博弈)
- 有关于Ajax的参数传递在MVC当中的应用
- 2016 多校 hdu 5723
- python核心编程学习笔记-2016-07-20-02-整型对象缓存
- linux常用命令
- CSS中不为人知Zoom属性的使用介绍(IE私有属性)
- css引入方式
- java中stringBuilder的用法
- [JZOJ4663]Seq