HDU The Boss on Mars

http://acm.hdu.edu.cn/showproblem.php?pid=4059

本题便是对于利用容斥原理进行欧拉函数的求解的拓展....  n = p1^a1*p2^a2*p3^a3*...*pk^ak

A1表示m的素因子分解中含有素因子p1, .... Ak表示m的素因子分解中含有pk,则与n互质的数A1至Ak性质均不满足,显然可以利用容斥原理来进行求解...

phi(n) = n - |A1| - |A2| - ... - |Ak| + |A1^A2| + ... + (-1)^k|A1^A2^...^Ak|, 显然对于求解与n的互质的数的和、平方和、立方和等等均可以利用该公式来进行相应的求解,只不过将其中元素换成我们需要求解的元素即可(其中对与求解互质的元素的和我们有更简便的答案: ans = n*phi(n)/2)

问题便变的如此的简单:


#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 10010;
const LL MOD = 1000000007;
bool is_prime[MAXN];
LL prime[MAXN];
LL factor[MAXN];
int T, len, cnt;
LL ans, n;

void Init()
{
    int i, j;
    len = 0;
    memset(is_prime, true, sizeof(is_prime));
    prime[len++] = 2;
    for(i = 3; i * i <= MAXN; i += 2)
    {
        if(is_prime[i])
        {
            prime[len++] = i;
            for(j = i * i; j < MAXN; j += i)
            {
                is_prime[j] = false;
            }
        }
    }
    for( ; i < MAXN; i += 2)
    {
        if(is_prime[i])
        {
            prime[len++] = i;
        }
    }
}

LL mult_mod(LL a, LL b, LL c)
{
    LL ret = 0;
    while(b)
    {
        if(b & 1) ret = (ret + a) % c;
        a = a * 2 % c;
        b >>= 1;
    }
    return ret;
}

LL power_mod(LL a, LL b, LL c)
{
    LL ret = 1;
    while(b)
    {
        if(b & 1) ret = mult_mod(ret, a, c);
        a = mult_mod(a, a, c);
        b >>= 1;
    }
    return ret;
}

LL get_sum(LL x)
{
    return (((((x*(2*x+1)%MOD)*(x+1))%MOD)*(3*x*x%MOD+3*x-1)%MOD)*power_mod(30,MOD-2,MOD))%MOD;
}

void cal_factor(LL x)
{
    cnt = 0;
    for(int i = 0; i < len && prime[i] * prime[i] <= x; ++i)
    {
        if(x % prime[i] == 0)
        {
            factor[cnt++] = prime[i];
            while(x % prime[i] == 0)
                x /= prime[i];
        }
    }
    if(x > 1)
    {
        factor[cnt++] = x;
    }
    return ;
}


void dfs(int id, LL cur, int ccount)
{
    if(id == cnt)
    {
        if(ccount & 1)
            ans = (ans - (power_mod(cur, 4, MOD) * get_sum(n/cur) % MOD))%MOD;
        else
            ans = (ans + (power_mod(cur, 4, MOD) * get_sum(n/cur) % MOD))%MOD;
        return ;
    }
    dfs(id + 1, cur, ccount);
    dfs(id + 1, cur * factor[id], ccount + 1);
    return ;
}

int main()
{
    //freopen("aa.in", "r", stdin);
    //freopen("bb.out", "w", stdout);

    Init();

    scanf("%d", &T);
    while(T--)
    {
        cin >> n;
        cal_factor(n);
        ans = 0;
        dfs(0, 1, 0);
        cout << (ans % MOD + MOD) % MOD << endl;
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值