您的位置:首页 > 其它

ACdream 1148 GCD SUM(数学:推理+数论:莫比乌斯函数)

2014-07-31 14:31 357 查看


GCD SUM

Time Limit: 8000/4000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others)

SubmitStatisticNext
Problem


Problem Description

给出N,M

执行如下程序:

long long ans = 0,ansx = 0,ansy = 0;

for(int i = 1; i <= N; i ++)

for(int j = 1; j <= M; j ++)

if(gcd(i,j) == 1) ans ++,ansx += i,ansy += j;

cout << ans << " " << ansx << " " << ansy << endl;


Input

多组数据,每行两个数N,M(1 <= N,M <= 100000)。


Output

如题所描述,每行输出3个数,ans,ansx,ansy,空格隔开


Sample Input

5 5
1 3



Sample Output

19 55 55
3 3 6



Hint

总数据小于50000


Source

dream


Manager

scaucontest

SubmitStatistic

这道题我用的数学推理方法做的

结果各种TLE,原因就是这个题要求比较高,不仅要推理出来还要了解莫比乌斯函数

我百度了一下,发现相关资料少得可怜

就不打算看了,有这时间还是先把基础打好把

推理如下:

对于1-n中的i找它与1-m中数互质的个数

如当前为1,则1-m中有m个数与1的约数为1,此时ans+=1, ansx+=m

如当前为2,则1-m中有m-m/2个数与2的约数为1,此时ans+=m-m/2, ansx+=(m-m/2)*2;

但是对于非素数要注意一下,如:

如当前为4,则1-m中有m-m/2(因为4中除1外较小的约数为2)个数与4的约数为1,此时ans+=m-m/2, ansx+=(m-m/2)*4

下面是我的代码,一直超时,至于莫比乌斯函数的解法我就不贴了,太冷门了

代码如下:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 100000
#define LL long long
using namespace std;

int a[MAXN+10], cnt=65;
int prime[70] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
283, 293, 307, 311, 313};

void euler(int n) {
int i, j;
memset(a, 0, sizeof(a));
for(i=0; i<cnt; ++i) {
for(j=prime[i]; j<=n; j+=prime[i]) {
if(a[j] == 0)
a[j] = prime[i];
}
}
for(i=1; i<=n; ++i)
if(a[i] == 0)
a[i] = i;
}

int main(void) {
int m, n;
LL ans1, ans2, ansx, ansy, tmp;
euler(MAXN);
while(scanf("%d%d", &n, &m) != EOF) {
ans1 = ans2 = m*n;
ansx = n*m*(n+1)/2;
ansy = m*n*(m+1)/2;

for(int i=2; i<=n; ++i) {
tmp = m/a[i];
ans1 -= tmp;
ansx -= tmp*i;
}
for(int j=2; j<=m; ++j) {
tmp = n/a[j];
ans2 -= tmp;
ansy -= tmp*j;
}
ans1 = max(ans1, ans2);
cout << ans1 << " " << ansx << " " << ansy << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: