来源
ICPC Pacific Northwest Regional Contest 2018 B
移步codeforces gym提交
或者vjudge
思路
真是个傻逼题,但是当时没有学完莫比乌斯
init是在用线性筛获得莫比乌斯函数的前缀和
然后用容斥原理得到解
注意溢出
前置知识
说明
莫比乌斯真是毒瘤,看了几天的《初等数论及其应用》和前置技能知识才学完
队友总是要不停刷题,不停下来好好看数论,这样是不对的
acm数论还是先停下来慢慢看完数论,不要舍不得花时间看理论,不然越看下去越一头雾水,因为很多时候推导就一句话
看完数论之后,对数论算法理解更好了
#include<bits/stdc++.h>
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const ll maxn=1e7+10;
const ll mod=1e9+7;
const ll inf=0x7f7f7f7f;
const ll N=1e7;
template<typename T>void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
ll T,a,b,c,d,k,ans;
int mu[maxn],p[maxn];
bool flg[maxn];
bool flag;
void init() {
int tot = 0;
mu[1] = 1;
for (int i = 2; i <= N; ++i) {
if (!flg[i]) {
p[++tot] = i;
mu[i] = -1;
}
for (int j = 1; j <= tot && i * p[j] <= N; ++j) {
flg[i * p[j]] = 1;
if (i % p[j] == 0) {
mu[i * p[j]] = 0;
break;
}
mu[i * p[j]] = -mu[i];
}
}
for (int i = 1; i <= N; ++i) mu[i] += mu[i - 1];
}
ll solve(int n,int m)
{
ll res=0;
for(int i=1,j;i<=min(n,m);i=j+1)
{
j=min(n/(n/i),m/(m/i));
res+=1ll*(mu[j]-mu[i-1])*(n/i)*(m/i);
}
return res;
}
int main()
{
init();
read(a);
read(b);
read(c);
read(d);
ans=solve(b,d)-solve(b,(c-1))-solve((a-1),d)+solve((a-1),(c-1));
printf("%lld\n",ans);
return 0;
}