ACM-ICPC 2018 瀋陽賽區網路預賽 c Convex Hull
阿新 • • 發佈:2018-12-12
莫比烏斯係數容斥; 把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; }