题意略。
思路:
可知对于一个拥有n个点的图来说,它至少需要有n - 1条边来维持连通性,而且数字1恰好与后面的n - 1个数字互质;
至于n个点的图可以产生合法的互质边的个数的上限,我们可以通过莫比乌斯反演来求得。
我这个题卡在寻找具体的质数对上,后来发现网上别的博客上说n到600时就可以产生1e5条互质边了。
也就是说,就算我是暴力寻找,n^2 * logn的复杂度,我找到600的时候,就已经可以凑足所有的边了。
哎。。。没有想到去打表看一下数据规模的。。。。
详见代码:
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 1e5 + 5; bool check[maxn]; LL prime[maxn],mu[maxn],tot; void mobius(){ memset(check,0,sizeof(check)); mu[1] = 1; tot = 0; for(LL i = 2;i < maxn;++i){ if(!check[i]){ prime[tot++] = i; mu[i] = -1; } for(int j = 0;j < tot;++j){ if(i * prime[j] > maxn) break; check[i * prime[j]] = true; if(i % prime[j] == 0){ mu[i * prime[j]] = 0; break; } else mu[i * prime[j]] = -mu[i]; } } } int gcd(int a,int b){ return b == 0 ? a : gcd(b,a % b); } int main(){ mobius(); LL n,m; while(scanf("%lld%lld",&n,&m) == 2){ LL sum = 0; for(LL i = 1;i <= n;++i){ LL len = n / i; sum += mu[i] * len * (len - 1) / 2; } if(m < n - 1 || m > sum){ printf("Impossible "); continue; } printf("Possible "); m -= (n - 1); for(int i = 2;i <= n;++i) printf("1 %d ",i); if(m == 0) continue; for(int i = 2;i <= n && m;++i){ for(int j = i + 1;j <= n && m;++j){ if(gcd(i,j) == 1){ printf("%d %d ",i,j); --m; } } } } return 0; }