欧拉函数 - Bi-shoe and Phi-shoe - LightOJ - 1370

欧拉函数 - Bi-shoe and Phi-shoe - LightOJ - 1370

题意:

n a a i a i b i 给出n个数字的序列a,对于每个数字a_i找到一个欧拉函数值大于等于a_i的数b_i,

b i s u m 求找到的所有数b_i的最小值之和sum

Input

T ( T 100 ) n ( n 10000 ) n a , 有T(T≤100)组数据,每组数据有两行,第一行给定n(n≤10000)第二行给出长度为n的序列a,

a i [ 1 , 1000000 ] a_i的取值范围为[1,1000000]

Output

s u m 输出一个数sum

Sample Input

3
5
1 2 3 4 5
6
10 11 12 13 14 15
2
1 1

Sample Output

Case 1: 22 Xukha
Case 2: 88 Xukha
Case 3: 4 Xukha

分析:

ϕ ( i ) i 1 首先,\phi(i)≤i-1恒成立,

a i < a j ( 1 i , j n ) b i b j 那么对于任意的a_i<a_j(1≤i,j≤n),必有b_i≤b_j,

a 因此,我们先对a数组排序,

a i ϕ ( j ) a i j j l a s t = j 接着对于每一个a_i,从前到后找到第一个满足\phi(j)≥a_i的整数j,累加上j,令last=j,

a i + 1 l a s t 然后对a_{i+1},从last开始继续向后枚举。

注意:

j a n j要枚举到超过a_n的某个值才行。

代码:

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>

#define ll long long

using namespace std;

const int N=1e6+10;

int T,n;
int primes[N],phi[N],cnt;
bool st[N];
int a[10010];

void get_prime(int n)
{
    phi[1]=0;
    for(int i=2;i<=n;i++)
    {
        if(!st[i])
        {
            primes[cnt++]=i;
            phi[i]=i-1;
        }
        for(int j=0;primes[j]*i<=n;j++)
        {
            int p=primes[j];
            st[p*i]=true;
            if(i%p==0)
            {
                phi[i*p]=p*phi[i];
                break;
            }
            else phi[i*p]=(p-1)*phi[i];
        }
    }
}

int main()
{  
    get_prime(N-1);
    int T;
    cin>>T;
    for(int t=1;t<=T;t++)
    {
        cin>>n;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        
        ll res=0;
        int last=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=last;j<N;j++)
                if(phi[j]>=a[i])
                {
                    last=j;
                    res+=j;
                    break;
                }
        }
        
        printf("Case %d: %lld Xukha\n",t,res);
    }
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/njuptACMcxk/article/details/107624646