欧拉函数 - 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, naaiaibi

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

Input

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

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

Output

输 出 一 个 数 s u m 输出一个数sum 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恒成立, ϕ(i)i1

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

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

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

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

注意:

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

代码:

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值