zoukankan      html  css  js  c++  java
  • 2014.11.12模拟赛【最大公因数】

    最大公因数(gcd.c/.cpp/.pas)

    题目描述

        给定正整数n,求。

    样例输入

    6

    样例输出

    15

    数据范围

    对于40%的数据:1<=n<=1000000

    对于100%的数据:1<=n<=3*10^12

    提示:保证答案不超过10^18

    原创题!

    ……好吧其实最后发现bzoj2705【longge的问题】跟这个一毛一样,但是这个数据更强

    不过我真是独立yy出来的

    首先,考虑gcd(i,n)==k的i有几个

    显然这是等价于gcd(j,n/k)==1的j有几个,其中1<=j<=n/k

    看到gcd==1,即j与n/k互质,你想到什么?显然是欧拉函数啊

    gcd(j,n/k)==1的j的个数就是phi(n/k),其中每个gcd(i,n)==k对答案的贡献是k,所以总的答案就是Σphi(n/k)*k,1<=k<=n且n%k==0

    显然这个式子等价于Σphi(k)*(n/k),1<=k<=n且n%k==0

    那么对n分解质因数,然后枚举它的每个因子取了多少个,算phi(k)*(n/k)就近似O(1)了

    总复杂度是O(sqrt(n))

    (所以完全可以开到10^15的,只是怕爆了long long要高精太麻烦)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<deque>
    #include<set>
    #include<map>
    #include<ctime>
    #define LL long long
    #define inf 0x7ffffff
    #define pa pair<int,int>
    #define mxprime 1500000
    using namespace std;
    bool mrk[1500010];
    LL prime[1000000],a[100];
    LL n,wrk,ans;
    int lenp,len;
    int b[100],now[100];
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void getprime()
    {
    	for (int i=2;i<=mxprime;i++)
    	  mrk[i]=1;
    	for (int i=2;i<=mxprime;i++)
    	  if (mrk[i])
    	  {
    	  	prime[++lenp]=(LL)i;
    	  	for(int j=2*i;j<=mxprime;j+=i)mrk[j]=0;
    	  }
    }
    inline void dfs(int step)
    {
    	if (step==len+1)
    	{
    		LL sum=1ll,tot=1ll;
    		for (int i=1;i<=len;i++)
    		{
    		  for (int j=1;j<=now[i];j++)
    		    sum*=a[i],tot*=a[i];
    		  if (now[i])sum=sum/a[i]*(a[i]-1);
    		}
    		ans+=sum*(n/tot);
    		return;
    	}
    	for(int j=0;j<=b[step];j++)
    	{
    		now[step]=j;
    		dfs(step+1);
    	}
    }
    int main()
    {
    	getprime();
    	n=wrk=read();
    	for (int i=1;prime[i]*prime[i]<=wrk;i++)
    	{
    		LL nowp=prime[i];
    		if (wrk%nowp==0)
    		{
    			a[++len]=nowp;
    			b[len]=1;
    			wrk/=nowp;
    			while (wrk%nowp==0)
    			{
    				b[len]++;
    				wrk/=nowp;
    			}
    		}
    	}
    	if (wrk!=1)
    	{
    		if (wrk==a[len])b[len]++;
    		else
    		{
    			a[++len]=wrk;
    			b[len]=1;
    		}
    	}
    	dfs(1);
    	printf("%lld
    ",ans);
    }
    

      

    ——by zhber,转载请注明来源
  • 相关阅读:
    NGINX基本概念
    IP地址进制转换
    路由
    ip ,网段, 网关
    ipaddress模块
    第53课 被遗弃的多重继承(上)
    const static valitate 区别
    第49课 多态的概念和意义 (虚函数virtual)
    第75课 图的遍历(深度优先遍历DFS)
    第74课 图的遍历(广度优先遍历BFS)
  • 原文地址:https://www.cnblogs.com/zhber/p/4093555.html
Copyright © 2011-2022 走看看