1. 程式人生 > >ACM-ICPC 2018 瀋陽賽區網路預賽 c Convex Hull

ACM-ICPC 2018 瀋陽賽區網路預賽 c Convex Hull

莫比烏斯係數容斥; 把2^2,3^2,這樣的數作為因子去容斥,並且把質數的平方作為特殊因子,如果一個影子可以分成奇數個不同的特殊因子,他的係數是-1,偶數個是-1,否則為0, 奇數x^2的整倍數的貢獻,即x^2,2*x^2,,這樣的數y的貢獻為(n-y)y^2,即x^4(1^2+2^2,(n/x)^2)-x^6**(1^3+2^3+3^3,(n/x)^3); 注意到p為1e11,會爆longlong,所以用__int128;

#include<bits/stdc++.h>
using namespace std;
typedef __int128 DLL;
const int N = 1e5+100;
int mul[N];
int prime[N];
int tot = 0;
bool vis[N];
long long n,p;
void print(DLL x){
    if(x == 0) return;
    print(x/10);
    printf("%d",x%10);
}

void init(){
    for(int i = 2;i < N;i ++){
        if(vis[i] == false) {
            prime[tot++] = i;
            mul[i] = -1;
        }
        for(int j = 0;j < tot && prime[j]*i< N;j ++){
            mul[prime[j]*i] = -mul[i];
            vis[i*prime[j]] = true;
            if(i%prime[j] == 0){
                mul[i*prime[j]] = 0;
                break;
            }
        }
    }
}
DLL one = 1;

DLL get(long long n,int q){
    if(q == 2) return one*n*(n+1)*(2*n+1)/6%p;
    if(q == 3) {
        DLL sum = one*n*(n+1)/2%p;
        return sum*sum%p;
    }
}

DLL pp(long long x,int y){
    DLL sum =1;
    for(int i = 1;i <= y;i ++) sum = sum*x%p;
    return sum;
}

int main(){
    init();
    while(scanf("%lld %lld",&n,&p)==2){
        DLL one = 1;
        long long ans = one*(n+1)*get(n,2)%p-get(n,3)%p;
        ans = (ans+p)%p;
        for(int i = 2;1LL*i*i <= n;i ++){
            if(mul[i] == 0) continue;
            DLL i4 = pp(i,4),i6 = pp(i,6);
            long long tmp =  one*(n+1)*i4%p*get(n/i/i,2)%p-one*i6%p*get(n/i/i,3)%p;
            tmp = (tmp+p)%p;
            ans =(ans+ tmp*mul[i])%p;
            ans =(ans+p)%p;
        }
        cout <<ans << endl;
    }
    return 0;
}