HDU4944 FSF’s game【因子和】【递推】

题目链接:

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;
}


猜你喜欢

转载自blog.csdn.net/u011676797/article/details/49338055