题目描述
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;
}