题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4944
题目大意:
给你一个数N,求出A、B分别为 1*1、1*2、…、1*N、2*2、2*3、…、2*N、……、N*N 中
A*B/gcd(A/K,B/K) 的值为多少。
解题思路:
设当 N = 1 时,ans[1] = 1*1/gcd(1,1) = 1。
N = 2 时,ans[2] = 1*1/gcd(1,1) + 1*2/gcd(1,2) + 2*2/gcd(2,2) + 2*2/gcd(1,1) = 9。
……
可看出:ans[N] = ans[N-1] + Σ N*i/gcd(N/K,i/K) (1<=i<=N),K 为 N 和 i 的公约数,也是
gcd(N,i)的约数。
Σ N*i/gcd(N/K,i/K) (1<=i<=N) ≡ N* Σ i * K/ (gcd(N,i) (1<=i<=N) ≡ N* Σ (i/c1 + i/c2 + …)
(cj 为 gcd(N,i)的所有约数,也是 i 的所有因子) 。
那么我们可以枚举所有的 cj。cj 是 i 的因子,那么 i/cj 就是因子的系数。那么对于所有的 i (1<= i
<= N)来说,我们可以计算出所有的可能数。对于cj,可得到系数为1、2、…、n/cj。
那么累加和就是 1+2+…+N/cj = (1 + N/cj)* (N/cj)/2。
则Σ N*i/gcd(N/K,i/K) (1<=i<=N) = N*(1 + N/cj)*(N/cj)/2。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define LL __int64
using namespace std;
LL A[500050],Ans[500050];
int main()
{
for(LL i = 1; i <= 500000; ++i)
{
for(LL j = i; j <= 500000; j += i)
{
A[j] += (j/i+1)*(j/i)/2; //因子j
}
}
Ans[1] = 1;
for(LL i = 1; i <= 500000; ++i)
{
Ans[i] = Ans[i-1] + A[i]*i; //递推
Ans[i] %= (1LL << 32);
}
int T,N,kase = 0;
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
printf("Case #%d: %I64d\n",++kase,Ans[N]);
}
return 0;
}