BJUTACM 吃饭的怪癖

2019ACM校赛的一个题,现场考虑的时候存了个素数数组,但由于没有考虑大素数(10^7以上量级)导致蜜汁RE,查了半天也没查出来...如果没搞错学校的电脑好像还是环境不太一样,导致我输入RE的数好像还能显示结果,回来之后改了个算法终于过了...

 

数论题,大眼瞪小眼之后发现和欧拉函数有关,\frac{(\varphi (m)\cdot m)}{2}即为结果,具体推导好像用到了最大公因数的性质

计算\varphi (m)可以使用连乘公式

现场还是心态不太一样,大素数这个错误都没有查出来,实在太菜了....

题目链接

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define ll long long

using namespace std;
bool judge(int a)
{
	if(a==1)
	{
		return 0;
	}
	if(a==2)
	{
		return 1;
	}
	else
	{
		for(int i=2;i<sqrt(a)+1;i++)
		{
			if(a%i==0)
			{
				return false;
			}
		}
		return true;
	}	
}


double euler(ll a)
{
	ll temp = a;
	double t = a;
	for(int i=2;i<sqrt(a)+1;i++)
	{
		if(temp%i==0&&judge(i)==1)
		{
			t *= ( 1- (1*1.0/i) ); 	
			while(temp%i==0)
			{
				temp /= i;//约掉所有这个素数 
			}
		}
	}
	if(judge(temp)==1)//如果现在还是个数 
	{
		t *= ( 1- (1*1.0/temp) );
 	} 
	if(temp==a)
	{
		temp = temp-1; 
		t = temp;
	}
//	cout<<t<<endl;
	return t;
}


int main(void)
{
	int a;
	while(cin>>a)
	{
		if(a==1)
		{
			cout<<1<<endl; 
			continue;	
		} 
		double temp = euler(a);		
		printf("%.0lf\n",temp*a*1.0/2);
	}
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值