ZZULIOJ--2853: 小A的游戏昵称(容斥原理)

题目描述

7是一个神奇的数字,小A喜欢在游戏中使用7作为昵称,但有时会出现冲突,小A就会在后边添加一个5或者3,如果再重复会使用他们的倍数。今天小A想让你算一下小于等于N的正整数中,是3、5、7的倍数的数的总和。

输入

输入一个正整数N,(1<=N<=1e9)

输出

输出所有是3、5、7倍数的总和。结果对998244353取模。

样例输入 Copy

20

样例输出 Copy

119

来源/分类

 考察容斥原理。

对于求三集合并集的公式:

  A∪B∪C=A+B+C - A∩B - A∩C - B∩C + A∩B∩C

 

 第一遍的时候把每个浅蓝色的圈里的加上,那么3个红色形状的部分就加了两次,深蓝色的部分加了3次,那么我们就减去图中

 三个紫色的形状的图形(就是两个圆相交的部分),那么红色部分就是加了一次了,深蓝色部分减去3次(和之前加的3次抵消),因为我们要算整个图形的面积,所以再把那个深蓝色部分加上。

1+2+3+....n:如果n是偶数前n项和为sum=((n+1)*n)/2;  如果n是奇数前n项和为sum=((n+1)/2)*n;

注意最后的输出加上再取模防止出现负数:printf("%lld\n",(sum1-sum2+998244353)%998244353);

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll sum1=0,sum2=0;
ll add(ll sum,ll n,ll a)
{
	ll b=(n/a);
	if(b%2==0) b=((b+1)*b)/2;
	else b=((b+1)/2)*b;
	
	
	b=((b%998244353)*a)%998244353;
	sum=(b+sum)%998244353;
	return sum;
	
}
int main() {
	ll n;
	scanf("%lld",&n);
	
	sum1=add(sum1,n,3);
	sum1=add(sum1,n,5);
	sum1=add(sum1,n,7);
	sum1=add(sum1,n,3*5*7);
	
//	cout<<sum1<<"..";
	sum2=add(sum2,n,15);
	sum2=add(sum2,n,21);
	sum2=add(sum2,n,35);
	
	printf("%lld\n",(sum1-sum2+998244353)%998244353);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/with_wine/article/details/121346312