题意:
给定一个整数n,求∑s(i,j)(1<=i<=j<=n)。其中s(i,j)=∑i*j/gcd(i/k,j/k)(k为i和j的公因子)。
解:
gcd(i/k,j/k) = gcd(i,j)/k , k 为i,j的公共因子
假设数为 6,12 , 则公共因子为1,2,3,6。 gcd(i,j)为6。 则 gcd(i,j)/k的答案是 6,3,2,1
因此 s(i,j) = ∑i*j / k , (k 为i,j的公共因子)
对于 对于 ∑s(n,i) (1<=i <= n) , 则可以写成
n * ( p1/p1 + 2*p1/p1 + 3*p1/p1 + ... ) * ( p2/p2 + 2*p2/p2 + 3*p2/p2 + ... )
= n * ∑ (sum(pi) / pi ) , 其中 pi 是某些数i与n的公因子, sum(pi)是有这些数的和
因为sum(pi) 中的每个数都是pi的倍数 , 则 sum(pi) / pi = num(pi)*( num(pi)+1)
num(pi)很好计算, 就是 1--n中能被 pi 整除的数的个数
对于 n*∑ i (i <= i <= j <= n) 最终答案就是 n * ∑ (num(pi) *(num(pi)+1) )
代码就特别短。。YM FF
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#define rep(i,j,k) for(unsigned i = j; i < k;i++)
using namespace std;
const unsigned int N = 500010;
unsigned int sum[N]={0},f[N]={0};
void pre(){
rep(i,1,N) sum[i] = sum[i-1] + i;
rep(i,1,N){
for(unsigned j=i , k = 1; j < N;j+= i ,k++){
f[j] = f[j] + (sum[k] * j);
}
}
rep(i,2,N)
f[i] += f[i-1];
}
int main(){
pre();
int t,tt=0;
int n;
scanf("%d",&t);
while(t--){
printf("Case #%d: ",++tt);
scanf("%d",&n);
printf("%u\n",f[n]);
}
return 0;
}