hdu4059 容斥原理的好题

27 篇文章 0 订阅
3 篇文章 0 订阅

1.首先要知道4次方求和的公式

2.注意求和公式中有除以30应该乘以30的逆

3.容斥原理

即 原来的所有和 -  1个质因数的倍数 + 2个质因数的倍数 - 3个质因数的倍数 + 4个质因数的倍数……

每个质因数的贡献就是getsum(n/link[i]) * four(link[i]),

比如质因数是2时,就是 (1^4+2^4+3^4+4^4......+(n/2)^4) * (2^4)

还要减掉 dfs(i+1,n/link[i]) * four(link[i]) ,乘以的数是four(link[i])

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <algorithm>
#include <ctime>
#include <vector>
#include <string>
#include <stack>
#include <queue>
using namespace std;
/*ll ext_gcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    ll x1,y1,d;
    d=ext_gcd(b,a%b,x1,y1);
    x=y1;
    y=x1-a/b*x;
    return d;
}
ll linear_equations(ll a,ll b,ll n) // a=b(mod n)
{
    ll x,y,d;
    d=ext_gcd(a,n,x,y);
    return (x%mod+mod)%mod;
}*/
#define mod 1000000007
#define ll long long
const int inv=233333335;
#define N 20000
int prime[N],is_prime[N],prime_num;
int link[100],cnt;
void init()
{
    for(int i=2;i<N;++i)
        if(!is_prime[i])
    {
        prime[prime_num++]=i;
        for(int j=i;j<N;j+=i)
            is_prime[j]=1;
    }
}
void get_divisor(ll n)
{
    cnt=0;
    for(int i=0;prime[i]*prime[i]<=n;++i)
        if(n%prime[i]==0)
        {
            link[cnt++]=prime[i];
            while(n%prime[i]==0)
                n/=prime[i];
        }
    if(n>1)
        link[cnt++]=n;
}
ll getsum(ll n)
{
    ll res=1;
    res*=n*(n+1)%mod;
    res*=(6*n*n%mod*n%mod+9*n*n%mod+n-1)%mod;
    res%=mod;
    res*=inv;
    res%=mod;
    return res;
}
ll four(ll n)
{
    ll a=n*n%mod;
    return a*a%mod;
}

ll dfs(int idx,ll n)
{
    ll res=0,temp;
    for(int i=idx;i<cnt;++i)
    {
        res=((res+(temp=getsum(n/link[i])*four(link[i])%mod))%mod+mod)%mod;
        res=((res-(temp=dfs(i+1,n/link[i])*four(link[i])%mod))%mod+mod)%mod;
    }
    return (res%mod+mod)%mod;
}
ll n;
int main ()
{
    int ncase;
    scanf("%d",&ncase);
    init();
    while(ncase--)
    {
        scanf("%I64d",&n);
        get_divisor(n);
        ll ans=getsum(n);
        ll t=dfs(0,n);
        printf("%I64d\n",((ans-t)%mod+mod)%mod);
    }
    return 0;
}







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值