https://vjudge.net/problem/LightOJ-1370
这是题目链接供大家练习用:
先介绍一下欧拉函数:
欧拉函数
定义:φ(n) 表示小于等于n的数中与n互质的数的个数。
基本性质:
① φ(1)=1 (很显然)
②对于φ(n),如果n是质数,φ(n) = n - 1。 (也很显然)
③对于φ(n),如果n是质数p的k次方(即n=p^k),对于φ(n) = p^k - p(k-1)。想了半天终于想懂为什么了。n是质数p的k次方,那么除了p的倍数其他的数都跟n互质,p的倍数有多少个呢。自然是n/p个了(相当于15里面有15/3个3的倍数),n/p就是p(k-1)。
④若n.m互质,φ(nm) = φ(n) * φ(m)。
⑤ 当n为奇数时,φ(2*n)=φ(n)。
⑥当n是质数时,φ(n * 2) = φ(n) * φ(2) = φ(n)。
⑦小于N且与N互质的所有数的和是φ(n)*n/2。
分析这个题目大致意思就是:
给出一些数字,对于每个数字找到一个欧拉函数值大于等于这个数的数,求找到的所有数的最小和。
思路:1.用数组存下每个数的欧拉函数值,然后一个个找。
2.利用欧拉函数的性质。对于给定的数x,欧拉函数值大于等于x的数一定大于x,于是我们从x+1开始找,看他之后的每一个数是不是素数,如果是的话,就break。为什么呢,因为纵观刚刚的那些性质我们发现,素数的欧拉函数值最大。所以我们碰到的第一个素数一定是我们要找的数。(意思就是因为有素数的性质得素数的欧拉值最大且为p-1,所以第一个达到要求的值一定为素数。
再次直接附上AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define inf 1000000000
using namespace std;
const int N= 1e6 + 5;
bool no_prime[N];
void init()
{
no_prime[0] = no_prime[1] = true;
for(int i = 2;i < N;i++)
{
if(no_prime[i])continue;
for(int j = 2 * i;j < N;j+=i)
{
no_prime[j] = true;
}
}
}
int main()
{
init();
int t;
cin >> t;
int Case = 1;
while(t--)
{
long long sum =0;
int n;
cin >> n;
int x;
for(int i = 1;i <= n;i++)
{
cin >> x;
for(int j = x + 1;;j++)
{
if(!no_prime[j])
{
sum += j;
break;
}
}
}
printf("Case %d: %lld Xukha\n",Case++,sum);
}
}