ACM-ICPC 2018 沈阳赛区网络预赛 G.Spare Tire (容斥)

题目链接:传送门

给你一个规律

给你一个n和一个m

求下标为1~n内所有与m互质的数的an的总和,答案mod1000000007

题解:

推出规律:

的前n项和为  

找出m的所有素因子 (素因子肯定不超过9个)

通过容斥定理找出1~n中与m不互质的数,例如m有一个素因子为2,那么2 4 6 8 10 12 14都不与m互质,那么我们可以提出一个2,总共有n/2个数,运用上面的式子进行求和,用了奇数个素因子要减去,偶数个素因子要加上,公式运用逆元。

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
ll inv2 = 500000004;//2的逆元 
ll inv6 = 166666668;//6的逆元 
const int MAXN = 10005;
int prime[MAXN+1];
void getPrime() {
	memset(prime, 0, sizeof(prime));
	for(int i = 2; i <= MAXN; i++){
		if(!prime[i]){
			prime[++prime[0]] = i;
		}
		for(int j = 1; j <= prime[0] && prime[j] <= MAXN/i; j++){
			prime[prime[j]*i]=1;
			if(i%prime[j]==0){
				break;
			}
		}
	}
} 

ll cc(ll n, ll i){
	n = n / i;
    return ( n%mod*(n+1)%mod*(2*n+1)%mod*inv6%mod  *i%mod*i%mod
		+ n%mod*(n+1)%mod*inv2%mod  *i%mod )%mod;
}


int main() {
	ll n, m;
	getPrime();
	while(~scanf("%lld%lld",&n,&m)){
		vector<int> q;
		int ans = m;
		for(int i = 1; i <= prime[0]; i++){
			if(m%prime[i] == 0){
				q.push_back(prime[i]);
				while(ans%prime[i] == 0){
					ans /= prime[i];
				}
			}
		}
		if(ans != 1){
			q.push_back(ans);
		}
		ans = cc(n,1);
		ll ans2 = 0;
		int len = q.size();
		ll tmp;
		for(int i = 1; i < (1<<len); i++){
			int flag = __builtin_popcount(i);//有多少个1 代表有多少个质因子 
			tmp = 1;
			for(int j = 0; j < len; j++){
				if(i&(1<<j)){
					tmp *= q[j];	
				}
			}
			tmp = cc(n,tmp);
			if(flag%2){//奇数个质因子 
				ans2 = (ans2 % mod + tmp % mod) % mod;
			} else {//偶数个质因子 
				ans2 = (ans2 % mod - tmp % mod + mod) % mod;
			}
		}
		printf("%lld\n",(ans%mod-ans2%mod+mod)%mod);
	}
	return 0;
} 

 

全部评论

相关推荐

点赞 评论 收藏
分享
三年之期已到我的offer快到碗里来:9硕都比不上9本
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-26 15:46
已编辑
字节国际 电商后端 24k-35k
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务