zoukankan      html  css  js  c++  java
  • HAOI2012 外星人

    题目链接 戳我

    能看懂的题目翻译:给你N,让你求(N=phi N)多少次N=1.

    根据唯一分解定理,以及题目中对(phi)的计算提示,我们知道,每一次计算,可以使得其中至多一个2变成1,不断地重复这个操作,这个数就会越来越小,直到达到1.

    所以我们求出来一个数中有多少个2作为因子即可。

    nlogn是可以暴力做的,但是对于1e6的数据范围可能略大了一些,所以我们考虑线性做法。

    (f(n))表示n中有多少个2.

    对于一个素数,(f(n)=f(n-1))。对于一个数a*b,(f(ab)=f(a)+f(b))

    之后就可以仿照欧拉筛来写了。

    最后注意一个细节,如果整个数里面没有2这个因子的话,(那这显然是奇数了吧)我们还需要额外的一步,使得它拥有2作为因子,所以ans++。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define MAXN 100010
    using namespace std;
    int t,m,x,y,tot;
    bool flag=false;
    long long ans;
    long long f[MAXN],not_prime[MAXN],prime[MAXN];
    inline void init()
    {
        f[1]=1;
        for(int i=2;i<=MAXN-10;i++)
        {
            if(not_prime[i]==0) prime[++tot]=i,f[i]=f[i-1];
            for(int j=1;j<=tot&&i*prime[j]<=MAXN-10;j++)
            {
                not_prime[i*prime[j]]=1;
                f[i*prime[j]]=f[i]+f[prime[j]];
                if(i%prime[j]==0) break;
            }
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        freopen("ce.out","w",stdout);
        #endif
        scanf("%d",&t);
        init();
        while(t--)
        {
            ans=0;
            flag=false;
            scanf("%d",&m);
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&x,&y);
                if(x==2) flag=true;
                ans+=1ll*f[x]*y;
    
            }
            if(flag==false) ans++;
        	printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    所有HTTP返回状态值,并说明用途
    几个简单的排序算法
    Linux命令大全
    存储过程中执行动态Sql语句
    IE8的背景不显示和图片错位 解决方案
    海量数据处理方法
    关于MSSQL的返回值问题
    SQL Server 2008不能修改表的解决方法
    转:读AD里特殊的属性in C#
    了解SMS的主要特性。
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10462208.html
Copyright © 2011-2022 走看看