南京理工大學第八屆程式設計大賽triple
阿新 • • 發佈:2019-02-13
題目連結:https://icpc.njust.edu.cn/Contest/749/D/
題目大意:在一定範圍內找出三個最大公約數為m且各不相同的數,問有多少中情況。
解題思路:剛開始的時侯用容斥寫,因為對於這個題而言質因子的分佈在1到10的5次方,所以就有大概9千多個質數,而我寫的容斥是n^2的,所以就超時,所以這題不能用質因子去容斥,而直接用n的因子,時間複雜度更低。所以n^2的容斥對某一個數的篩選表現更好,因為一個數的質因子很少。後來用莫比烏斯反演寫了一發,果然快多了。F(m)=n/m*(n/m-1)*(n/m-2)。
莫比烏斯反演:
/* ******************************** Author : danmu Created Time : 2016年04月17日 星期日 23時28分00秒 File Name : triple.cpp Vim Command copy -> yy paste -> p P del this line -> dd Ctrl-Z -> u U copy into system -> "+y ******************************** */ #include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <iomanip> #include <string> #include <vector> #include <cstdio> #include <stack> #include <queue> #include <cmath> #include <list> #include <map> #include <set> #define ULL unsigned long long #define PI 3.1415926535 #define INF 0x3f3f3f3f #define LL long long #define eps 1e-8 #define MAX 100000 using namespace std; bool vis[MAX+10]; int mu[MAX+10],prime[MAX+10],cnt; void mobi(int n){ memset(vis,false,sizeof(vis)); mu[1]=1; cnt=0; for(int i=2;i<=n;++i){ if(!vis[i]){ prime[cnt++]=i; mu[i]=-1; } for(int j=0;j<cnt&&i*prime[j]<=n;++j){ vis[i*prime[j]]=1; if(i%prime[j]) mu[i*prime[j]]=-mu[i]; else{ mu[i*prime[j]]=0; break; } } } } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int t; mobi(100000); scanf("%d",&t); while(t--){ int n,m; LL ans=0; scanf("%d%d",&n,&m); LL tmp=n/m; /*if(tmp<3){ printf("0\n"); continue; }*/ for(int i=1;i<=tmp;++i) ans+=mu[i]*(tmp/i*(tmp/i-1)*(tmp/i-2)/6); printf("%lld\n",ans); } return 0; }