[The simplest entry problem for Mobius inversion] B.Coprime Integers

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;
}

Guess you like

Origin blog.csdn.net/STL_CC/article/details/108305561