【欧拉】 UVA 11426 GCD - Extreme (II)
2015-07-31 10:25
489 查看
这次不挂题目地址。。。因为UVa的感觉。。。好吧我还是贴题目吧。
Problem J
GCD Extreme (II)
Input: Standard Input
Output: Standard Output
Given the value of N, you will have to find the value of G. The definition of G is given below:
Here GCD(i,j) means the greatest common divisor of integer i and integer j.
For those who have trouble understanding summation notation, the meaning of G is given in the following code:
Input
The input file contains at most 100 lines of inputs. Each line contains an integer N (1<N<4000001). The meaning of N is given in the problem statement. Input is terminated by a line containing a single zero.
Problemsetter: Shahriar Manzoor
Special Thanks: SyedMonowarHossain
题目要求的是范围内的所有gcd( i , j )( j > i ) 和。。。我们的第一反应自然是去求 gcd( i , n) 然后预处理成o(1)输出。。。
然而这时候发现数字太大不能直接求。
看题解的时候给的公式是这样的
for(int i=1;i<=4000000;i++)
{
for(int j=2*i;j<=4000000;j+=i)
{
ans[j]+=oura[j/i]*i;
}
ans[i]+=ans[i-1];
}
然而不理解,之后去问了人之后得到了这个的证明方法
-------------------------------------------分割线-----------------------------------------------------
首先我们把gcd打成表。
| 1 2 3 4 5 6 7 8
-----+-------------------------------------------------------
1 | 1 1 1 1 1 1 1 1
2 | 1 2 1
2 1 2 1 2
3 | 1 1 3 1 1 3 1
1
4 | 1 2 1 4 1
2 1 4
5 | 1 1 1 1 5 1 1 1
6 | 1 2 3 2 1 6 1
2
7 | 1 1 1 1 1 1 7 1
8 | 1 2 1 4 1 2 1
8
显然,黄底的部分就是我们找的答案
这时候我们把2的倍数的取出来看看的话
| 1 2 3 4 5 6 7 8
-----+-------------------------------------------------------
1 | 1 1 1 1 1 1 1 1
2 | 1 2
1 2 1
2 1 2
3 | 1 1 3 1 1 3 1 1
4 | 1 2 1 4
1 2 1
4
5 | 1 1 1 1 5 1 1 1
6 | 1 2 3 2
1 6 1 2
7 | 1 1 1 1 1 1 7 1
8 | 1 2 1 4
1 2 1
8
你会发现如果再对每项除以2就是和刚刚一样的图了
此时的所有2变成1,我们用欧拉函数便可很快的将它们取出来
同理可推广到所有数字,因此有了之前的公式。。。
-------------------------------------------分割线-----------------------------------------------------
代码其实可以不用了吧。。。毕竟刚刚讲的挺详细了(是这样吗?)
而且我的代码风格感觉并不是很好。
Problem J
GCD Extreme (II)
Input: Standard Input
Output: Standard Output
Given the value of N, you will have to find the value of G. The definition of G is given below:
For those who have trouble understanding summation notation, the meaning of G is given in the following code:
G=0; for(i=1;i<N;i++) for(j=i+1;j<=N;j++) { G+=gcd(i,j); } /*Here gcd() is a function that finds the greatest common divisor of the two input numbers*/ |
The input file contains at most 100 lines of inputs. Each line contains an integer N (1<N<4000001). The meaning of N is given in the problem statement. Input is terminated by a line containing a single zero.
Output
For each line of input produce one line of output. This line contains the value of G for the corresponding N. The value of G will fit in a 64-bit signed integer.Sample Input Output for Sample Input
10 100 200000 0 | 67 13015 143295493160 |
Special Thanks: SyedMonowarHossain
题目要求的是范围内的所有gcd( i , j )( j > i ) 和。。。我们的第一反应自然是去求 gcd( i , n) 然后预处理成o(1)输出。。。
然而这时候发现数字太大不能直接求。
看题解的时候给的公式是这样的
for(int i=1;i<=4000000;i++)
{
for(int j=2*i;j<=4000000;j+=i)
{
ans[j]+=oura[j/i]*i;
}
ans[i]+=ans[i-1];
}
然而不理解,之后去问了人之后得到了这个的证明方法
-------------------------------------------分割线-----------------------------------------------------
首先我们把gcd打成表。
| 1 2 3 4 5 6 7 8
-----+-------------------------------------------------------
1 | 1 1 1 1 1 1 1 1
2 | 1 2 1
2 1 2 1 2
3 | 1 1 3 1 1 3 1
1
4 | 1 2 1 4 1
2 1 4
5 | 1 1 1 1 5 1 1 1
6 | 1 2 3 2 1 6 1
2
7 | 1 1 1 1 1 1 7 1
8 | 1 2 1 4 1 2 1
8
显然,黄底的部分就是我们找的答案
这时候我们把2的倍数的取出来看看的话
| 1 2 3 4 5 6 7 8
-----+-------------------------------------------------------
1 | 1 1 1 1 1 1 1 1
2 | 1 2
1 2 1
2 1 2
3 | 1 1 3 1 1 3 1 1
4 | 1 2 1 4
1 2 1
4
5 | 1 1 1 1 5 1 1 1
6 | 1 2 3 2
1 6 1 2
7 | 1 1 1 1 1 1 7 1
8 | 1 2 1 4
1 2 1
8
你会发现如果再对每项除以2就是和刚刚一样的图了
此时的所有2变成1,我们用欧拉函数便可很快的将它们取出来
同理可推广到所有数字,因此有了之前的公式。。。
-------------------------------------------分割线-----------------------------------------------------
代码其实可以不用了吧。。。毕竟刚刚讲的挺详细了(是这样吗?)
而且我的代码风格感觉并不是很好。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define LL long long using namespace std; int oura[4000010]; int prime[300000],cont; long long ans[4000010]; void init() { cont=0; for(int i=2;i<=4000000;i++) { if(!oura[i]) { prime[cont++]+=i; oura[i]=i-1; } for(int j=0;j<cont;j++) { if(prime[j]>4000000/i) break; if(i%prime[j]!=0) oura[prime[j]*i]=oura[i]*(prime[j]-1); else { oura[prime[j]*i]=oura[i]*prime[j]; break; } } } ans[0]=0; for(int i=1;i<=4000000;i++) { for(int j=2*i;j<=4000000;j+=i) { ans[j]+=oura[j/i]*i; } ans[i]+=ans[i-1]; } } int main() { init(); int n; while(~scanf("%d",&n) && n) { printf("%lld\n",ans ); } return 0; }
相关文章推荐
- struts2使用response和request功能
- java集合浅谈(一)
- windows操作系统
- 7月28日15家中国域名商(国际域名)解析量报告
- Javascript中this关键字详解
- AndroidManifest.xml文件详解(uses-feature)
- SpingMVC中的HandlerMapping
- Android--service里 onstart()onStartCommand()方法的区别
- _sntprintf
- [leetcode 72]Edit Distance
- 遇到的Fragment中使用setAdapter()设置ListView报空指针解决方案
- avascript处理JSON数据格式
- socket粗解
- 无修改区间查询 BNU Can you answer these queries I
- width:auto和width:100%的区别
- 判断一个数字中是否包含两个相同的子串
- Win10发布2天安装机量已接近1000万 要破纪录
- 实例讲解SQL Server加密功能
- linux记录----date使用初记
- C++中的 extern "C"