您的位置:首页 > 产品设计 > UI/UE

TOJ 3990.I guess the gift is a bag! II(质因数、欧拉函数好题)

2016-07-20 13:09 363 查看
题目链接 : http://acm.tju.edu.cn/toj/showp3990.html

Coach Yu has lots of bags, every bag has its number. And what is more, he wants to send these bags to acm team-member. But he requires that if you get the bag and its number is b, you need to count how many number smaller than b and co-prime with b. If you can’t count it, he won’t send the bag to you.

However, G.D.R and Hacb learn the The Euler function to solve the problem. And they are so friendly that they like to share the function to you, so you can get the bag.

The Euler function is:

F(b) = b *( 1 - 1/p1) ( 1 - 1/p2)……(1-1/pn)

Notes: pi is the ith Prime factors of b, and there will be no such i and j which i<>j but pi=pj.

………….

  这道题的题目只有短短的几行,意思也很简单,就是求欧拉函数的值,算法的思想就是求出质因数然后算一下即可,但写起来却没有想象的那么简单,wa、超时各种错误,这道题写了好久,真的是短小精悍啊,也可以看出自己的算法和编程基础还是不过关。按照惯例先反思一下自己犯过的错误吧

首先超时两次,自己竟然无知到对一个10^12大小的数枚举所有的质因子,并且还是在while循环里边,也就是每输入一次样例,都要重复的去判断是否为质数,以及求解质因数,感觉自己脑子瓦塔拉,预先将质数存入一个数组然后去算不就行了嘛,对于n以内的质数,下面这种方法效率貌似比枚举要高一些:

int enumPrime(int n) //将n以内的质数存入一个数组
{
int p=0;
for(int i=0;i<=n;i++)
{
is_prime[i]=true;
}
is_prime[0]=is_prime[1]=false;
for(int i=2;i<=n;i++)
{
if(is_prime[i])
{
prime[p++]=i;
for(int j=2*i;j<=n;j+=i)
{
is_prime[j]=false;
}
}
}
return p;
}


另外还有一个小知识点就是10^12大小的数只需要找1e6范围内的指数即可,这个为什么我也不太懂,数很大时素数很稀疏?1e6之外只有它本身?

还有一点,是一个数学素养方面的问题,自己不注意WA了好多次,这道题要求欧拉函数,也就是求(1-1/p)形式的积,但是1/p是个小数啊,所以不能直接这么算,用ans/p就好了,哎,真的是细节决定成败!

#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int N=1e6+1;
bool is_prime
;
int prime
;
using namespace std;
int  sieve (int n)
{
int p=0;
for(int i=0;i<=n;i++)
{
is_prime[i]=true;
}
is_prime[0]=is_prime[1]=false;
for(int i=2;i<=n;i++)
{
if(is_prime[i])
{
prime[p++]=i;
for(int j=2*i;j<=n;j+=i)
{
is_prime[j]=false;
}
}
}
return p;
}

int main()
{
long long b;
int maxnum=1e6;
int num = sieve(maxnum);
while(~scanf("%lld",&b)&&b!=0){
if(b==1){
printf("0\n");
continue;
}
long long euler=b;
for(int i=0;i<num && prime[i]<=b;i++){
if(b%prime[i]==0){
euler=euler*(prime[i]-1)/prime[i];
while(b%prime[i]==0)
b=b/prime[i];
}
}
if(b>1)
euler=euler/b*(b-1);
printf("%lld\n",euler);
}
}


上面这种解法就是从质因数的定义出发,通过找出一个合数的所有素数因子来求解质因子,实际上根本不需要求素数就可以求出质因子,像下面这样即可:

int enumprimefactor(int n){
int temp=n,num=0;
for(int i=2;i*i<=n;i++){
if(temp%i==0)
primefactor[num++]=i;
while(temp%i==0)
temp/=i;
}
if(temp>1)
primefactor[num++]=temp;
return num;
}


因此这道题用上面的方法很容易就可解出来了,哎,想起了一句话:别人传说我20。

#include<cstdio>
using namespace std;
int main()
{
long long  n;
while(scanf("%lld",&n) && n)
{
long long  temp=n;
long long  ans=n;
for(long long i=2;i*i<=temp;i++)
{
if(temp%i==0)
{
ans=ans-ans/i;
while(temp%i==0)
{
temp=temp/i;
}
}

}
if(temp>1)
ans=ans-ans/temp;
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  toj 数论 质因子