HDU 4059 (容斥原理,快速幂,逆元)


题目大意是求1-n中与n互质的数的四次方累加。

由于正解比较麻烦,所以我们可以先求出1-n的前n个四次方累加,减去跟n不是互质的数的四次方

1-n的四次方累加和公式 = n*(n+1)*(2*n+1)*(3*n*n+3*n-1)/30

先将n的质因数求出,然后比n小的并且是质因数的倍数的数的四次方 ,由于会多减去一些数,因此要用到容斥定理。

例如2 的倍数有2,4,6,8 。3 里面的倍数也有6,因此会多减。

2的倍数四次方可以提取出来2的次数方,并用1-n/2的四次方累加和公式。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

#define MOD 1000000007
#define  ll long long
const int maxn = 1e4 + 5;
vector<ll> q;
int prime[maxn];
int vis[maxn];
int cnt;

ll pow_k(ll a, ll  b)
{
	ll  res = 1;
	while(b)
	{
		if(b & 1)
			res =(res*a) % MOD;
		a = (a*a)%MOD;
		b >>= 1;	
	}
	return res%MOD;
}

ll pow_f(ll x)
{
	ll res = (x*x) % MOD;
	res = (res * x) %MOD;
	res = (res * x) % MOD;
	return res % MOD;
}

ll sum(ll n)
{
	ll res = pow_k(30, MOD-2);
	ll s = n*(n+1) % MOD;
	s = (s*(2*n+1)%MOD) % MOD;
	s = (s*(3*n*n%MOD + 3*n%MOD-1+MOD)%MOD) % MOD;
	s = (s*res) % MOD;
	return s%MOD;
}

ll dfs(int index, ll n)
{
	ll res = 0, temp;
	int len = q.size();
	for(int i = index; i< len; i++)
	{
		temp = q[i];
		res = (res + sum(n/temp)*pow_f(temp)%MOD) % MOD;
		res = (res - dfs(i+1, n/temp)*pow_f(temp)% MOD + MOD) % MOD;
	}
	return res % MOD;
}

void is_prime()
{
	memset(vis, 0, sizeof vis);
	for(int i = 2; i <= maxn; i ++)
	{
		if(vis[i])
			continue ;
		prime[cnt++] = i;
			for(int j = i*i; j <= maxn; j+=i)
					vis[j] = 1;	
	}
}

int main()
{
	int t;
	scanf("%d", &t);
	while(t--)
	{
		cnt = 0;
		is_prime();
		ll n;
		q.clear();
		scanf("%lld", &n);
		ll temp = n;
		for(int i = 0; i < cnt && prime[i] < temp; i++)
			if(temp%prime[i] == 0)
			{
				q.push_back(prime[i]);
				while(temp%prime[i] == 0)
					temp /= prime[i];
			}	
		if(temp != 1)
			q.push_back(temp);
		ll res = 0;
		int size = q.size();
		for(int i = 1; i < (1 << size); i++) // 容斥原理 
		{
			int flag = 0;
			temp = 1;
			for(int j = 0; j < size; j++)
			{
				if(i & (1 << j))
					temp = (temp*q[j]) % MOD,flag = !flag;
			}
			ll t = (sum(n/temp)*pow_f(temp)) % MOD;
			if(flag)
				res = (res + t) % MOD;
			else
				res = (res - t + MOD) % MOD;	
		}
		printf("%lld\n", (sum(n)-res + MOD) % MOD);
		//ll res = (sum(n) - dfs(0, n)%MOD + MOD) % MOD;
		//cout << res << endl;
		// dfs 是递归式 实现容斥原理 
		
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38295645/article/details/80349026