hdu4059 2011年大连区域赛 数论(四次方和 容斥原理 取模)

57 篇文章 0 订阅
32 篇文章 0 订阅

The Boss on Mars

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2666    Accepted Submission(s): 846


Problem Description
On Mars, there is a huge company called ACM (A huge Company on Mars), and it’s owned by a younger boss.

Due to no moons around Mars, the employees can only get the salaries per-year. There are n employees in ACM, and it’s time for them to get salaries from their boss. All employees are numbered from 1 to n. With the unknown reasons, if the employee’s work number is k, he can get k^4 Mars dollars this year. So the employees working for the ACM are very rich.

Because the number of employees is so large that the boss of ACM must distribute too much money, he wants to fire the people whose work number is co-prime with n next year. Now the boss wants to know how much he will save after the dismissal.
 

Input
The first line contains an integer T indicating the number of test cases. (1 ≤ T ≤ 1000) Each test case, there is only one integer n, indicating the number of employees in ACM. (1 ≤ n ≤ 10^8)
 

Output
For each test case, output an integer indicating the money the boss can save. Because the answer is so large, please module the answer with 1,000,000,007.
 

Sample Input
  
  
2 4 5
 

Sample Output
  
  
82 354
Hint
Case1: sum=1+3*3*3*3=82 Case2: sum=1+2*2*2*2+3*3*3*3+4*4*4*4=354



题意:

求解(1~n)区间中与n互质的书的四次方和

题解:

转化为【1,n】的四次方和 - 不与n互质的数的四次方和

其中不与n互质的数

可以转化为求解n的质因子,然后利用容斥原理求解得到所有的与n不互质的数字

比如说30,质因子为 2  3  5 

2 的倍数有  2 4 6 8 10.。。。30   提一个2得到 2*(1,2,3,4,5,,,,15)

3 的倍数有  3 6 9 。。。。 30

5的倍数有   5 10 15.。。。。30

2*3 的倍数  6 12 18.。。。。。30

2*5的倍数  10 20 30

3*5的倍数  15 30

2*3*5的倍数 30

然后对每一行的四次方和进行容斥原理求解

每一行可以转化为2 ^4* (1 ^4 + 2^4 +3^4 +.....+ 15^4)这样的形式

就可以求得答案了


注意:

本题求解的时候一定要注意防止溢出后再取模

传值的时候也全部需要传long long型的数据类型,最好把所有数据类型都定义成long long

四次方求和公式里面先取模再除以30,因此要求得30的模逆元,即:分子乘以30的模逆元



四次方求和公式:

(n+1)^5-n^5=5n^4+10n^3+10n^2+5n+1 
n^5-(n-1)^5=5(n-1)^4+10(n-1)^3+10(n-1)^2+5(n-1)+1 
…… 
2^5-1^5=5*1^4+10*1^3+10*1^2+5*1+1 
全加起来 
(n+1)^5-1^5=5*(1^4+2^4()+3^4+4^4+……+n^4)+10*(1^3+2^3+3^3+4^3+……+n^3)+10*(1^2+2^2+3^2+4^4+……+n^2)+5*(1+2+3+4+……+n)+n 
因为1^3+2^3+3^3+4^3+……+n^3=[n(n+1)/2]^2 
1^2+2^2+3^2+4^4+……+n^2=n(n+1)(2n+1)/6 
1+2+3+4+……+n=n(n+1)/2 
所以1^4+2^4+3^4+4^4+……+n^4 
={[(n+1)^5-1^5]-10*[n(n+1)/2]^2-10*n(n+1)(2n+1)/6-5*n(n+1)/2-n}/5 
=n(n+1)(2n+1)(3n^2+3n-1)/30


模逆元:

//------------模逆元--------------//
LL qpowMod(LL m,LL n,LL p)
{
    LL ans=1;
    LL temp=m;
    while(n>0)
    {
        if(n&1)
            ans=ans*temp%p;
        temp=temp*temp%p;
        n>>=1;
    }
    return ans;
}
LL getInverse(LL a,LL p)
{
    return qpowMod(a,p-2,p);
}
//--------------------------------//



求解质因子:

//-----------求质因子-------------//
void devide(LL n)
{
    tot=0;
    for(LL i=2;i*i<=n;i++){
        if(n%i==0){
            a[tot++]=i;
            while(n%i==0)
                n=n/i;
        }
    }

    if(n>1)//这里要记得
        a[tot++]=n;
}
//--------------------------------//




#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define LL long long
const LL mod=1000000007;
int a[100],tot;
LL num;

//------------模逆元--------------//
LL qpowMod(LL m,LL n,LL p)
{
    LL ans=1;
    LL temp=m;
    while(n>0)
    {
        if(n&1)
            ans=ans*temp%p;
        temp=temp*temp%p;
        n>>=1;
    }
    return ans;
}
LL getInverse(LL a,LL p)
{
    return qpowMod(a,p-2,p);
}
//--------------------------------//

//-----------求质因子-------------//
void devide(LL n)
{
    tot=0;
    for(LL i=2;i*i<=n;i++){
        if(n%i==0){
            a[tot++]=i;
            while(n%i==0)
                n=n/i;
        }
    }

    if(n>1)//这里要记得
        a[tot++]=n;
}
//--------------------------------//


LL calc(LL n)
{
    LL ans=n;
    ans=ans*(n+1)%mod;
    ans=ans*(2*n+1)%mod;
    ans=ans*((3*n*n%mod+3*n-1)%mod)%mod;
    ans=(ans*num)%mod;
    return ans;
}

//--------------------------------//
LL power(LL x)
{
    return (((x*x)%mod*x)%mod*x)%mod;
}
//--------------------------------//


//----------容斥原理--------------//
LL deal(LL n)
{
    LL ans=0;
    for(LL i=1;i<(1LL<<tot);i++)
    {
        int sum=0,temp=1;
        for(int j=0;j<tot;j++)
        {
            if(i&(1LL<<j)){
                sum++;
                temp=(temp*a[j])%mod;
            }
        }
        if(sum&1)
            ans=(ans%mod+(calc(n/temp)%mod*power(temp))%mod)%mod;
        else
            ans=(ans%mod-(calc(n/temp)%mod*power(temp))%mod+mod)%mod;
    }
    return ans;
}
//--------------------------------//


int main()
{
    LL T,n;
    num=getInverse(30,mod);//求逆元
    //freopen("in.txt","r",stdin);
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&n);
        if(n==1){
            puts("0");
            continue;
        }
        devide(n);
        LL t1=calc(n);
        LL t2=deal(n);
        printf("%lld\n",(t1-t2+mod)%mod);
    }
    return 0;
}




用队列进行容斥原理似乎快了一倍啊
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define LL long long
#define MAXN 1000000
const LL mod=1000000007;
int a[MAXN],tot;
LL num;

//------------模逆元--------------//
LL qpowMod(LL m,LL n,LL p)
{
    LL ans=1;
    LL temp=m;
    while(n>0)
    {
        if(n&1)
            ans=ans*temp%p;
        temp=temp*temp%p;
        n>>=1;
    }
    return ans;
}
LL getInverse(LL a,LL p)
{
    return qpowMod(a,p-2,p);
}
//--------------------------------//

//-----------求质因子-------------//
void devide(LL n)
{
    tot=0;
    for(LL i=2;i*i<=n;i++){
        if(n%i==0){
            a[tot++]=i;
            while(n%i==0)
                n=n/i;
        }
    }

    if(n>1)//这里要记得
        a[tot++]=n;
}
//--------------------------------//


LL calc(LL n)
{
    LL ans=n*(n+1)%mod;
    ans=(ans*((2*n%mod+1)%mod))%mod;
    LL temp=3*(n*n%mod);
    temp=(temp%mod+3*n%mod-1)%mod;
    ans=(ans*temp)%mod;

    return ans*num%mod;
}

//--------------------------------//
LL power(LL x)
{
    return (((x*x)%mod*x)%mod*x)%mod;
}
//--------------------------------//


//----------容斥原理--------------//
LL deal(LL n)
{
    LL que[10000],pos=0,sum=0;
    int q[10000];
    q[pos]=1;
    que[pos++]=-1;

    for(LL i=0;i<tot;i++){
        LL k=pos;
        for(LL j=0;j<k;j++){
            LL temp=power(q[j]*a[i]);
            q[pos]=q[j]*a[i]%mod;

            LL t;
            if(que[j]>0)
                t=temp%mod;
            else
                t=-temp%mod;
            que[pos]=t*(-1)*calc(n/q[pos]);
            if(que[pos]>0)
                que[pos]=que[pos]%mod;
            else
                que[pos]=-((-que[pos])%mod);
            pos++;
        }
    }
    for(LL i=1;i<pos;i++)
        sum=(sum+que[i])%mod;
    return sum;
}
//--------------------------------//


int main()
{
    LL T,n;
    num=getInverse(30,mod);//求逆元
   // freopen("in.txt","r",stdin);
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&n);
        if(n==0){
            puts("0");
            continue;
        }
        devide(n);
        LL temp=calc(n);
        LL t=deal(n);
        printf("%lld\n",(temp-t+mod)%mod);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值