题目链接: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; }
南京理工大学第八届程序设计大赛triple
最新推荐文章于 2024-12-18 13:55:57 发布