ACM-ICPC 2018 Xuzhou Online 徐州赛区网络赛(待更新)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lfhase/article/details/82562826

ACM-ICPC 2018 Xuzhou Online 徐州赛区网络赛(待更新)


D Easy Math

题目链接
题面:

(骗搜索)
Given a positive integers n , Mobius function μ ( n ) is defined as follows:

μ ( n ) = { 1 n = 1 ( 1 ) k n = p 1 p 2 p k 0 o t h e r
Given two integers mm, nn, please calculate i = 1 m μ ( i n ) i = 1 m μ ( i n ) .
Input
One line includes two integers m (1 \le m \le 2e9)m(1≤m≤2e9), n (1 \le n \le 1e12)n(1≤n≤1e12) .

Output
One line includes the answer .

样例输入 复制
2 2
样例输出 复制
-1
题目来源
ACM-ICPC 2018 徐州赛区网络预赛

题意:

计算 Σ i = 1 m μ ( i n )

思路:

莫比乌斯反演+筛法。

f ( m , n ) = Σ i = 1 m μ ( i n ) = Σ i = 1 m μ ( i ) [ g c d ( i , n ) = 1 ] μ ( n )

代入莫比乌斯函数,得
f ( m , n ) = μ ( n ) Σ i = 1 m μ ( i ) Σ d | g c d ( i , n ) μ ( d )

变换一下,有
f ( m , n ) = μ ( n ) Σ d | n μ ( d ) Σ d | i m μ ( i ) = μ ( n ) Σ d | n μ ( d ) f ( m / d , d )

枚举n的所有因子,用筛法求 f ( m , n )
事实上,
m = 1 f ( m , n ) = μ ( n )
n = 1 f ( m , n ) = Σ i = 1 n ( i )
所以再用杜教筛处理一下前缀和就好了,复杂度不会算(tao

AC代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X  first
#define Y  second
#define REP(i,st,ed)    for(int i=st;i<=ed;++i)
#define IREP(i,st,ed)   for(int i=ed;i>=st;--i)
#define TCASE(T)    cin>>T;while(T--)


const int MAXN = 2000005;
const ll MOD = 2333333 ;
const int INF = 1e9+7;

int _;

using namespace std;

ll N, M;

int rua(ll n)
{
    int cnt = 0;
    for(ll i = 2; i * i <= n; ++i)
    {
        if(n%i == 0)
        {
            n /= i;
            ++cnt;
            if(n%i == 0) return 0;
        }
    }
    if(n > 1) ++cnt;
    return cnt&1?-1:1;
}


bool check[MAXN];
int prime[MAXN];
int mu[MAXN];
int summ[MAXN];

void Moblus()
{
    memset(check,0,sizeof(check));
    mu[1] = 1;
    int tot = 0;
    for(int i=2; i<MAXN; ++i)
    {
        if(!check[i])
        {
            prime[++tot] = i;
            mu[i] = -1;
        }

        for(int j=1; j<=tot; ++j)
        {
            if(i*prime[j]>MAXN) break;
            check[i*prime[j]] = 1;
            if(i%prime[j]==0)
            {
                mu[i*prime[j]] = 0;
                break;
            }
            else    mu[i*prime[j]] = -mu[i];
        }
    }
    summ[0] = 0;
    for(int i=1; i<MAXN; ++i) summ[i] = summ[i-1]+mu[i];
}

ll get_mu(ll num)
{
    if(num<MAXN)    return 1LL*mu[num];
    else    return 1LL*rua(num);
}


struct p_my_map{
    ll x;
    int ans,next;
}p_e[MAXN+5];

int p_ans=0,p_num=0;
int p_head[MOD+5];

void p_ins(ll x,int sum)
{
    int j=x%MOD;
    p_e[++p_num]=(p_my_map){x,sum,p_head[j]};
    p_head[j]=p_num;
}

int p_calc(ll n)
{
    if(n<MAXN) return summ[n];
    for(int i=p_head[n%MOD];i;i=p_e[i].next)
        if(p_e[i].x==n)return p_e[i].ans;
    int sum=1,q=sqrt(n);
    for(int i=2;i<=q;i++)
        sum-=p_calc(n/i);
    q=n/(q+1);
    for(int i=1;i<=q;i++)
        sum-=(n/i-(n/(i+1)))*p_calc(i);
    p_ins(n,sum);
    return sum;
}


struct my_map
{
    ll x, y;
    int ans;
    int next;
} e[MAXN+5];

int ans=0,num=0;
int head[MOD+5];

void ins(ll x,ll y,int sum)
{
    int j=(x+y)%MOD;
    e[++num]=(my_map)
    {
        x,sum,head[j]
    };
    head[j]=num;
}

ll calc(ll n, ll m)
{
    if(m==0)    return 0;
    if(m==1)    return get_mu(n);
    if(n==1)    return p_calc(m);
    int tmp = get_mu(n);
    if(!tmp)    return 0;

    for(int i=head[(n+m)%MOD]; i; i=e[i].next)
        if(e[i].x==n&&e[i].y==m)   return e[i].ans;

    ll sum=0;
    for(ll i=1;i*i<=n;++i)
    {
        if(!(i==1||n%i==0)) continue;
        sum += get_mu(i)*calc(i,m/i);
        if(n/i!=i)  sum += get_mu(n/i)*calc(n/i,m/(n/i));
    }
    sum*=tmp;
    ins(n,m,sum);
    return sum;
}

int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.in","w+",stdout);
    Moblus();
    scanf("%lld%lld",&M,&N);

        int nnn = rua(N);
        if(nnn==0)  printf("%d\n",0);
        else
        {
            num = p_num = 0;
            printf("%lld\n",calc(N,M));
        }

}

猜你喜欢

转载自blog.csdn.net/Lfhase/article/details/82562826
今日推荐