source
ICPC Pacific Northwest Regional Contest 2018 B
moved to codeforces gym submission
or vjudge
Ideas
It’s a silly question, but I didn’t finish learning Mobius at the time.
Init was using a linear sieve to obtain the prefix of the Mobius function and
then using the principle of tolerance and exclusion to get the solution.
Pay attention to overflow
Pre-knowledge
Mobius inversion of
linear sieving
function
Description
Mobius is really a malignant tumor. After watching "Elementary Number Theory and Its Application" and the knowledge of
prerequisite skills for a few days, his teammates always have to keep reading the questions, and don’t stop to read the number theory. Is this wrong
acm number theory or first Stop and finish reading number theory slowly. Don't be reluctant to spend time looking at the theory, otherwise the more you look at it, the more you will get confused, because most of the time the derivation is just one sentence
.
#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;
}