【莫比乌斯反演最简单的入门题】B.Coprime Integers

来源

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

猜你喜欢

转载自blog.csdn.net/STL_CC/article/details/108305561