题目链接:https://cn.vjudge.net/problem/LightOJ-1370
题意:给出n个数的欧拉值,求这n个数的和的最小值。
欧拉函数:在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)。
性质:
欧拉函数是
积性函数——若m,n互质,
![](https://gss3.bdstatic.com/-Po3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D140/sign=daa516337cec54e745ec1e1a89399bfd/bd3eb13533fa828b5d8406eefa1f4134970a5a1c.jpg)
特殊性质:当n为奇数时,
, 证明与上述类似。
![](https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D96/sign=52a5c55ef1246b607f0ebe72eaf8e29d/8cb1cb134954092331f8f8739558d109b3de492e.jpg)
若n为质数则
![](https://gss3.bdstatic.com/7Po3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D85/sign=31100df17bd98d1072d40134203fd0be/a5c27d1ed21b0ef404180353dac451da80cb3ece.jpg)
相邻两个素数之间合数的欧拉值都小于较小素数的欧拉值。不会证明。。。
所以只要找到大于并且最接近这个数的素数就好了。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAX_N 2000000
int prime[MAX_N/2];
bool is_prime[MAX_N+1];
void sieve(int n)
{
int p = 0;
memset(is_prime,true,sizeof(is_prime));
is_prime[0] = is_prime[1] = false;
for(int i = 2; i <= n/2; i++)
{
if(is_prime[i])
prime[p++] = i;
for(int j=0; j<p && prime[j]*i<=n; j++)
{
is_prime[prime[j]*i]=false;
if(i%prime[j]==0)
break;
}
}
}
int main()
{
int t;
sieve(MAX_N);
scanf("%d",&t);
for(int tt=1;tt<=t;tt++)
{
int n;
scanf("%d",&n);
long long sum=0;
while(n--)
{
int x;
scanf("%d",&x);
for(int i=x+1;;i++)
{
if(is_prime[i])
{
sum+=i;
break;
}
}
}
printf("Case %d: %lld Xukha\n",tt,sum);
}
return 0;
}