2015多校第8场 HDU 5382 GCD?LCM! 数论公式推导

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5382

题意:函数lcm(a,b):求两整数a,b的最小公倍数;函数gcd(a,b):求两整数a,b的最大公约数。函数[exp],其中exp是一个逻辑表达式。如果逻辑表达式exp是真,那么函数[exp]的值是1,否则函数[exp]的值是0。例如:[1+2>=3] = 1 ,[1+2>=4] = 0。

求S(n)的值。

 

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e6+10;
const int mod = 258280327;
bool isprime[maxn];
LL prime[maxn], primecnt, num[maxn];
LL G[maxn], T[maxn], F[maxn], S[maxn];
LL qsm(LL a, LL n){
    LL ret = 1;
    while(n){
        if(n&1) ret = ret*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ret;
}
void pre_deal(){
    memset(isprime, true, sizeof(isprime));
    memset(num, 0, sizeof(num));
    for(int i=2; i<maxn; i++){
        if(isprime[i]){
            num[i]++;
            for(int j=i+i; j<maxn; j+=i){
                isprime[j] = false;
                num[j]++;
            }
        }
    }
    for(int i=2; i<maxn; i++){
        if(isprime[i]){
            prime[primecnt++]=i;
        }
    }
}
void INIT()
{
    pre_deal();
    G[0] = 0;
    for(int i=1; i<maxn; i++){
        G[i] = qsm(2, num[i]);
    }
    memset(T, 0, sizeof(T));
    memset(F, 0, sizeof(F));
    memset(S, 0, sizeof(S));
    for(int i=1; i<maxn; i++){
        for(int j=i; j<maxn; j+=i){
            T[j]=(T[j]+G[j/i-1])%mod;
        }
    }
    F[1] = S[1] = 1;
    for(int i=2; i<maxn; i++){
        F[i] = ((F[i-1]+2*i-1+mod)%mod-(T[i-1]%mod)+mod)%mod;
        S[i] = (S[i-1] + F[i])%mod;
    }
}
int main()
{
    INIT();
    LL n;
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lld", &n);
        printf("%lld\n", S[n]);
    }
    return 0;
}

 

posted @ 2017-08-09 16:22  zxycoder  阅读(251)  评论(0编辑  收藏  举报