A - Bi-shoe and Phi-shoe | 数论 | 欧拉函数Euler Function

欧拉函数
最开始想的肯定是打表找规律,发现没啥规律(因为上次那个差分序列的题还写了半天出现一次出现两次出现四次)。
意思就是已知某数字与它互质且小于它的数共有m个,求在所有符合情况的数字中最小的那一个。我想把phi[a] = p记录下来,然后按照p排序,return a,最后将所有值相加。但是实现的时候比较麻烦,因为p不是连续的,而且也不单调,怎么确定最小的a就很难搞。这种思路硬搞也可以的题解
卡了半天看了题解之后发现是利用了欧拉函数的一个性质:

若A是素数,则phi(A) = A - 1(跟除了它自己之外的互质)。

欧拉函数的值一定是素数先出现
如果phi[A] = m,m存在,那么第一个使得phi[ num[t] ] = m的num[t]一定是素数。又因为我们要取min{num[1], num[2]…}所以只要对素数进行处理就好啦。

#include <bits/stdc++.h>

using namespace std;

#define ll long long
const int MAX_N = 1000010;

int T, n, cnt;
ll ans;

int isprime[MAX_N], cprime[MAX_N];

void prime()
{
    memset(isprime, 1, sizeof(isprime));
    isprime[1] = isprime[0] = 0;
    for(int i = 2;i <= MAX_N;i++)
    {
        if(isprime[i])
        {
            for(int j = i+i;j <= MAX_N;j += i)
                isprime[j] = 0;

            cprime[cnt++] = i;
            //printf("cprime[%d] = %d\n", cnt-1, i);
        }
    }
}

int bisearch(int i)
{
    int l = 0, r = cnt, mid;
    while(l <= r)
    {
        mid = (l + r)/2;
        //printf("l = %d  r = %d  mid = %d\n", l, r, mid);

        if(cprime[mid] > i)
            r = mid - 1;
        else
            l = mid + 1;
    }

    //printf("l = %d  r = %d  mid = %d\n", l, r, mid);

    for(int w = r; ;w++)
        if(cprime[w] > i)
        {
            //printf("return cprime[%d] = %d\n", w, cprime[w]);
            return cprime[w];
        }
}


int main()
{
    prime();

    scanf("%d", &T);

    for(int i = 1;i <= T;i++)
    {
        ans = 0;
        scanf("%d", &n);
        for(int m = 1;m <= n;m++)
        {
            int x;
            scanf("%d", &x);

            ans += bisearch(x);
            //printf("ans = %lld\n", ans);

        }

        printf("Case %d: %lld Xukha\n", i, ans);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值