Lightoj 1370 Bi-shoe and Phi-shoe(欧拉函数)

刚开始学习数论,加油。

历经几个小时,终于过了这道题,感动。

大致思路是先欧拉函数打表,然后二分查找。

这里先介绍lower_bound()函数:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的。

头文件必须包含<algorithm>。使用举例:数组a[]={1,3,4,8},lower_bound(a,a+2,2)-a的返回值就是1(需要注意的是这里必须减去a),返回值1也就是数组中3的下标;那么lower_bound(a,a+4,9)-a的返回值应该是什么?是4,这是因为如果所有元素都小于val,则返回last的位置。

本题的一个小坑就是虽然单个的欧拉函数值都是在int的范围内,但是当数据足够多(接近10000)足够大(接近或大于1000000)时,是有可能超出int的范围的,因此变量s(最终的结果)应为范围更大的数据类型。因为这个WA了好多次,改成long long就过了,心累。

附上完整代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#define N1 2000000+10
using namespace std;

int eular[N1];

void makelist(){//创建欧拉函数表 
	for(int i=1;i<N1;i++)
		eular[i]=i;
	for(int i=2;i<N1;i+=2){
		eular[i]/=2;
	}
	for(int i=3;i<N1;i+=2){
		if(eular[i]==i)
		for(int j=i;j<N1;j+=i){
			eular[j]=eular[j]/i*(i-1);
		}
	}
}

int main(){
	int t,a,b=1;
	makelist();
	for(int i=2;i<N1;i++)
		eular[i]=max(eular[i],eular[i-1]);//表中后面的项可能小于前面的项,而这些项在本题中都是没有意义的,故将之扩大,便于二分查找
	scanf("%d",&t);
	while(t--){
		int n;
		long long s=0;
		scanf("%d",&n);
		for(int i=0;i<n;i++){
			scanf("%d",&a);
			s+=lower_bound(eular+2,eular+N1,a)-eular;
		}
		cout<<"Case "<<b++<<": "<<s<<" Xukha"<<endl;
	}
	return 0;
} 

此外,看到一个比较牛的性质是:
给你一个数t,让你求使得phi(n)>=t的最小的n,这个n就是大于t的最小的素数。按这个性质的话就可以打个素数表解决这道题,不过本人比较懒,就没有去做啦。

最后,总结就是审题一定要仔细,各方面都要考虑到,不能想当然!(第一篇博文,如有不对之处,欢迎指出。)



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值