/** 题目:A - Bi-shoe and Phi-shoe 链接:https://vjudge.net/contest/154246#problem/A 题意:每一个数都有一个得分,它的得分就是,假定这个数为n,那么<n且与n互质的数的个数就是n的得分; 注意这里<n说明不是完全求欧拉函数,当n=1的时候值为0;其他和欧拉函数求法一样。 现在给定n个数xi,对每一个数xi找一个最小的满足条件的数yi,使得yi的得分>=xi这个数。 求n个数xi对应找出来的yi的和。 思路: 第一种做法 递推求出欧拉函数数组,然后特殊处理1的值设定为0; 然后对要求的n个数排序,从小到大找一个满足条件的yi,之后的数肯定在大于等于yi的数中找。 不断将yi后移就行了。仔细想想就明白了。 第二种做法 不需要排序,预处理递推数组后,因为素数r的欧拉函数之为r-1;而两个素数之间的距离不超过log(r); 那么对每一个数xi可以从自身开始向上递增最多log(xi)就可以找到>=xi的欧拉函数; */ #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int maxn = 1000100; ///获得单个数的欧拉函数 /* ll getEuler(ll x) { ll res = x; for(int i = 2; i*i<=x; i++){ if(x%i==0){ res = res/i*(i-1); while(x%i==0) x/=i; } } if(x>1){ res = res/x*(x-1); } return res; }*/ int a[10005]; int n, cas=1; ll euler[maxn]; ///递推求一段欧拉函数,非最简版 void Eulers(ll x) { int mas = 0; for(int i = 1; i <= x; i++) euler[i] = i; for(int i = 2; i <= x; i++) { if(euler[i]==i){//判断素数 for(int j = i; j <= x; j+=i){ euler[j]=euler[j]/i*(i-1); } } } ///由于本题目要求<n的欧拉函数,不可以等于n;所以当n为1的时候,满足条件的个数为0; ///****************************实际上1的欧拉函数值为1;所以这里是一个针对本题的特例才要改为0; euler[1] = 0; } void solve1() { sort(a,a+n); int p = 1; ll ans = 0; for(int i = 0; i<n; i++){ while(euler[p]<a[i]){ p++; } ans += p; } printf("Case %d: %lld Xukha ",cas++,ans); } void solve2() { ll ans = 0; for(int i = 0; i<n; i++){ for(int j = a[i]; 1; j++){///两个素数之间距离最多log(n); if(euler[j]>=a[i]){ ans += j; break; } } } printf("Case %d: %lld Xukha ",cas++,ans); } int main() { int T; Eulers(maxn); cin>>T; while(T--){ scanf("%d",&n); for(int i = 0; i<n; i++) scanf("%d",&a[i]); //solve1(); solve2(); //printf("euler(%lld) = %lld ",x,getEuler(x)); //printf("MAX(euler(%lld)) = %lld ",x,Eulers(x)); } return 0; }