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);
    }
}

鸽了训练 去看电影了 哈哈。

posted @ 2019-03-05 18:01  灬从此以后灬  阅读(292)  评论(0编辑  收藏  举报