codeforces 1009D Relatively Prime Graph【欧拉函数】
题目:戳这里
题意:要求构成有n个点,m条边的无向图,满足每条边上的两点互质。
解题思路:
显然1~n这n个点能构成边的条数,就是2~n欧拉函数之和(x的欧拉函数值代表小于x且与x互质的数的个数。
因此m>n-1 && m <= sum成立则可以构成无向图。
接着求出1e5以内的欧拉函数,求和可以发现前1000项的欧拉值就已经远远大于1e5。
所以m条边直接两层循环暴力即可。
附本人代码:
1 #include <bits/stdc++.h> 2 typedef long long ll; 3 const int maxn = 1e5+10; 4 const ll inf = 1e18; 5 const ll mod = 1e9+7; 6 using namespace std; 7 ll cnt[maxn]; 8 ll euler[maxn]; 9 void geteuler() { 10 memset(euler, 0, sizeof(euler)); 11 euler[1] = 1; 12 for(ll i = 2; i < maxn; ++i) { 13 if(!euler[i]) { 14 for(ll j = i; j < maxn; j+=i) { 15 if(!euler[j]) euler[j] = j; 16 euler[j] = euler[j]/i * (i - 1ll); 17 } 18 } 19 } 20 } 21 ll gcd(ll a, ll b) {return b?gcd(b,a%b):a;} 22 int main(){ 23 ll n, m; 24 ll sum = 0; 25 scanf("%lld %lld", &n, &m); 26 geteuler(); 27 for(ll i = 2; i <= n; ++i) { 28 sum += euler[i]; 29 } 30 31 // printf("%lld\n", sum); 32 if(sum < m || m < n - 1) { 33 puts("Impossible"); 34 return 0; 35 } 36 puts("Possible"); 37 for(ll i = 1; i <= n; ++i) { 38 for(ll j = i + 1; j <= n; ++j) { 39 if(gcd(i,j)==1) { 40 printf("%lld %lld\n", i, j); 41 --m; 42 if(!m) return 0; 43 } 44 } 45 } 46 return 0; 47 }