CF 2018 Battle of Brains GYM 102062 F
https://codeforces.com/gym/102062/attachments/download/8213/2018-battle-of-brains-en.pdf
https://codeforces.com/gym/102062
题意 对于一个数k 向自己的约数连一条无向边(不含1,和本身) ,递归每个约数进行相同的操作,最后构成树or图。
问 1-n有多少个数进行上述操作形成树。
解析 分析发现 将一个数质因数分解 当它有三个及以上质因数就是图,所以我们质数筛筛出来所有的素数标记为1,再两两相乘,小于1e6的标记为1
前缀和预处理答案就好了。
#include <bits/stdc++.h> #define pb push_back #define mp make_pair #define fi first #define se second #define all(a) (a).begin(), (a).end() #define fillchar(a, x) memset(a, x, sizeof(a)) #define huan printf("\n") #define debug(a,b) cout<<a<<" "<<b<<" "<<endl #define ffread(a) fastIO::read(a) using namespace std; typedef long long ll; const int maxn = 1e6+10; const int inf = 0x3f3f3f3f; const ll mod = 1000000007; const double epx = 1e-6; const double pi = acos(-1.0); //head------------------------------------------------------------------ int check[maxn],prime[maxn],pos,sum[maxn]; void Prime(int N) { pos=0; sum[1]=1; for (int i = 2 ; i <= N ; i++) { if (!check[i]) prime[pos++] = i,sum[i]=1; for (int j = 0 ; j < pos && i*prime[j] <= N ; j++) { check[i*prime[j]] = 1; if (i % prime[j] == 0) { break; } } } } int main() { Prime(1000000); for(int i=0;i<pos;i++) { for(int j=i;j<pos;j++) //根本不会超时 break是关键 虽然两层循环但是 o(n)的复杂度 { if(1ll*prime[i]*prime[j]<=1000000) sum[prime[i]*prime[j]]=1; else break; } } for(int i=2;i<=1000000;i++) sum[i]+=sum[i-1]; int n,t,kase=1; scanf("%d",&t); while(t--) { scanf("%d",&n); int d=__gcd(n,sum[n]); printf("Case %d: %d/%d\n",kase++,sum[n]/d,n/d); } }
鸽了训练 去看电影了 哈哈。