The Boss on Mars
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3270 Accepted Submission(s): 1074
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
Author
ZHANG, Chao
Source
2011 Asia Dalian Regional Contest
Recommend
lcy
算法分析:
题意:
求[1, n]中与n互质的数的四次方和。
实现
四次方和不好算,不可能预处理每个数的4次方,空间和时间都不允许。
1^4 + 2^4 + ... + n^4 这样的式子还是有公式的。其结果为 n(n+1)(2n+1)(3n^2+3n+1)/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
(n-1)^5-(n-2)^5=5(n-2)^4+10(n-2)^3+10(n-2)^2+5(n-2)+1
...
...
...
2^5-1^5=5*1^4+10*1^3+10*1^2+5*1+1
需要用到的公式有
1^2+2^2+...+n^2=n*(n+1)*(2*n+1)/6;
1^3+2^3+...+n^3=n^2*(n+1)^2/4;
然后全部相加起来,经行化简 就可以就可以得到f(n)
所以,我们可以通过容斥原理把1~n与n不互质的数求出来,求出它们四次方和,再用总的减去即可。
如何求跟不互质的数,跟以前一样,把n的素因子枚举出来,容斥原理做,
假定n存在2这样的素因子,那么n与2,4,6,8。。。这样的数都不互质。我们可以求出2,4,6,8,。。。的四次方和。
简单观察,可以发现,2^4+4^4+6^4+8^4+... = 2^4 * ( 1^4 + 2^4 + 3^4 + 4^4... ),仍然可以使用前n次方和的公式计算。
1/30取模问题
因为要取模,有除法因此我们需要求逆元
a^b=1(mod m)
这里介绍两种方法
1)
因为30与1000000007互斥 因此由费马小定理可知这是的逆元为(30^(mod-2))%(mod);
2)
a/b mod m = (a mod (m*b) )/m;
代码用的是第一种方法。
注意:算一下,就要取模,不然答案会错
还有n可能等于1/
代码实现:
二进制:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int fac[100] ;
ll n,inv,sum;
int factor(ll m)
{
sum=0;
ll tmp=m;
for(ll i=2;i*i<=tmp;i++)
if(tmp%i==0)
{
fac[sum++]=i;
while(tmp%i==0)
tmp/=i;
}
if(tmp>1) fac[sum++]=tmp;
return 0;
}
ll f(ll n)// 四次方和公式:1/30*n*(n+1)(2n+1)(3n^2+3n-1)
{
ll ans=n;
ans=(ans*(n+1))%mod;
ans=(ans*(2*n+1))%mod;
ans=(ans*((3*n*n+3*n-1)%mod))%mod;
ans=(ans*inv)%mod;
return ans;
}
ll quick_qow(ll a,ll b,ll k)
{
long long res=1;
while(b>0)
{
if(b%2) res=(res*a)%k;
a=(a*a)%k;
b/=2;
}
return res;
}
int work()
{
ll ans=0;
for(int i = 1; i < (1<<sum); i++) //从0~2^n-1个状态,遍历每一个集合,i可能也是从1开始的,因为有的题没有选0个的
{
ll tmp=1,cnt=0;
for(int j = 0; j < sum; j++) //遍历二进制的每一位
{
if(i&(1 << j))//判断二进制第j位是否存在
{
tmp*=fac[j];
cnt++;
}
}
ll t=f(n/tmp)%mod;
tmp=(tmp*tmp)%mod;
tmp=(tmp*tmp)%mod;
tmp=(tmp*t)%mod;
if(cnt&1)
ans=(ans+tmp)%mod;
else
ans=(ans-tmp)%mod;
}
ll t=(f(n)-ans+mod)%mod;
printf("%lld\n",t);
}
int main()
{
int T;
inv=quick_qow(30,mod-2,mod);
cin>>T;
while(T--)
{
scanf("%lld",&n);
if(n==1) {cout<<0<<endl;continue;}
factor(n);
work();
}
return 0;
}
dfs:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int fac[100] ;
ll n,inv,sum,ans;
int factor(ll m)
{
sum=0;
ll tmp=m;
for(ll i=2;i*i<=tmp;i++)
if(tmp%i==0)
{
fac[sum++]=i;
while(tmp%i==0)
tmp/=i;
}
if(tmp>1) fac[sum++]=tmp;
return 0;
}
ll f(ll n)// 四次方和公式:1/30*n*(n+1)(2n+1)(3n^2+3n-1)
{
ll ans=n;
ans=(ans*(n+1))%mod;
ans=(ans*(2*n+1))%mod;
ans=(ans*((3*n*n+3*n-1)%mod))%mod;
ans=(ans*inv)%mod;
return ans;
}
ll quick_qow(ll a,ll b,ll k)
{
long long res=1;
while(b>0)
{
if(b%2) res=(res*a)%k;
a=(a*a)%k;
b/=2;
}
return res;
}
void dfs(int i,int cnt,ll tmp)
{
ll ret=tmp;
ll t=f(n/tmp)%mod;
tmp=(tmp*tmp)%mod;
tmp=(tmp*tmp)%mod;
tmp=(tmp*t)%mod;
if(cnt&1)
ans=(ans+tmp)%mod;
else
ans=(ans-tmp)%mod;
for(int j=i+1;j<sum;j++)
dfs(j,cnt+1,ret*fac[j]%mod);
}
int main()
{
int T;
inv=quick_qow(30,mod-2,mod);
cin>>T;
while(T--)
{
scanf("%lld",&n);
if(n==1) {cout<<0<<endl;continue;} //注意n=1
factor(n);
ans=0;
for(int i=0;i<sum;i++)
dfs(i,1,fac[i]%mod);
printf("%lld\n",(f(n)-ans+mod)%mod);
}
return 0;
}