3389. 【NOIP2013模拟】Heaven Cow与God Bull

Description

__int64 ago,there’s a heaven cow called sjy…

A god bull named wzc fell in love with her…

As an OI & MOer,wzc gave sjy a quesiton…

给定一个整数n,求一个整数m,满足m<=n,并且m/phi(m)的值最大。

注:phi(m)代表m的欧拉函数,即不大于m且与m互质的数的个数。

Input

第一行是一个整数T,表示该测试点有T组数据。

接下来T行,每行一个整数n,意义如上所述。

Output

输出一共T行,每行一个整数m。

若对于某个n,有不止一个满足条件的m,则输出最小的m。

Sample Input

1

10

Sample Output

6

Data Constraint

对于10%的数据, n<=1000

对于30%的数据, n<=10^10

对于60%的数据, n<=10^2000

对于100%的数据,T<=100,n<=10^25000。

Solution

  • 法一:数学方法
    我们要求

    MAX(φ(m)m)m M A X ( φ ( m ) m ) 的 m

    又有 φ(m)=mp|mp1p φ ( m ) = m ∗ ∏ p | m p − 1 p
    那么带入ans,
    MAX(1p|mp1p)m M A X ( 1 ∏ p | m p − 1 p ) 的 m

    分子最小时,分母不变,分数最大,所以要求的是
    MIN(p|mp1p)m M I N ( ∏ p | m p − 1 p ) 的 m

    因为p都是质数,而且除了φ(1)外,其他的φ(1)
    φ(1)外,其他的φ(1)都是小于1的,所以越乘越小,所以把2,3,5,7,11…..直到快爆掉n位置后,这个数就是满足要求的数了。

  • 法二:暴力打标找规律
    首先打个暴力,找出1到一个较大但能在10秒内出解的数的所有答案,再找规律,注意要用实数类型,不能用整型(我就是在这里卡了好久,愣是没找到规律),最终改回来后一眼找出规律,这个规律好好找啊。
    所以说,暴力要打对啊!

要打高精度

打个比较和高精乘就好了。

离散大法

发现有多组数据,我们一开始给输入的数排一个序就好了。
常练离散大法好,危难来时把命保。

预处理

预处理出所有可能的答案,即2,2*3,2*3*5,2*3*5*7,…,然后每次O(n)找答案,或者二分找,速度没并有太大影响。


两种代码供你参考,嘻嘻

Code1

#include
#include
#include
#include
#include
#define ll long long
#define N 25200
#define MOD 100000000000000
using namespace std;
char st[N];
ll a[N],ans[6200][N/10],p[60000];
bool bz[60000];
ll t,len,s,k;
bool max(ll a[],ll b[]){
    if(a[0]>b[0]) return 1;
    if(b[0]>a[0]) return 0;
    for(int i=a[0];i>=1;i--){
        if(a[i]>b[i]) return 1;
        if(a[i]return 0;
    }
    return 0;
}
ll length(ll x){
    int l=0;
    while(x>0){
        x/=10;
        l++;
    }
    return l;
}
int main(){
    for(int i=2;i<=58880;i++){
        if(!bz[i]){
            p[++p[0]]=i;
            for(int j=i;j<=58880/i;j++) bz[i*j]=1;
        }
    }
    ans[0][0]=ans[0][1]=1;
    for(int i=1;i<=p[0];i++){
        ans[i][0]=ans[i-1][0];
        for(int j=1;j<=ans[i][0];j++) ans[i][j]=ans[i-1][j]*p[i];
        for(int j=1;j<=ans[i][0];j++){
            ans[i][j+1]+=ans[i][j]/MOD;
            ans[i][j]%=MOD;
        }
        while(ans[i][ans[i][0]+1]>0){
            ans[i][0]++;
            ans[i][ans[i][0]+1]+=ans[i][ans[i][0]]/MOD;
            ans[i][ans[i][0]]%=MOD;
        }
    }
    scanf("%d",&t);
    while(t--){
        scanf("%s",st+1);
        len=strlen(st+1);
        s=a[0]=0;k=1;
        for(int i=1;i<=len;i++){
            s+=(st[len-i+1]-'0')*k;
            k*=10;
            if(k==MOD){
                a[++a[0]]=s;
                s=0;k=1;
            }
        }
        if(s>0) a[++a[0]]=s;
        int l=0,r=p[0],mid=0,i=0;
        while(l<=r){
            mid=(l+r)/2;
            if(max(ans[mid],a)) r=mid-1;
            else{
                l=mid+1;
                i=l;
            }
        }
        printf("%lld",ans[i-1][ans[i-1][0]]);
        for(int j=ans[i-1][0]-1;j>=1;j--){
            int x=length(ans[i-1][j]);
            for(int k=1;k<=14-x;k++) printf("0");
            printf("%lld",ans[i-1][j]);
        }
        printf("\n");
    }
    return 0;
}

Code2

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
typedef int arr[25005]; 
using namespace std;
int i,j,k,l,t,n,m,tt,zhi[100007],tot;
int ans1[101][25005];
arr ans,b,c;
bool bz[1000007];
char s[25005];
struct node{
    arr shu;
    int o;
}a[101];
bool bijiao(arr x,arr y){
    int i,j,k,l;
    if(x[0]>y[0]){
        return 0;
    }
    else if(x[0]==y[0]){
        fod(i,x[0],1){
            if(x[i]>y[i]){   
                return 0;
            }
            else if (x[i]return 1;
        }
        return 0;
    } 
}
bool cmp(node x,node y){
    return bijiao(x.shu,y.shu);    
}
void cheng(int x){
    int i,j,k,l,o=0;
    memset(b,0,sizeof(b));
    fo(i,1,ans[0]){
        b[i]=b[i]+ans[i]*x+o;
        b[i+1]+=b[i]/10;
        b[i]=b[i]%10;
    }
    for(b[0]=ans[0];b[b[0]+1];){
        b[++b[0]+1]+=b[b[0]]/10;
        b[b[0]]=b[b[0]]%10;
    }
}
void work(int x){
    int i,j,k,l;
    fo(i,tot,zhi[0]){
        l=i;
        cheng(zhi[i]);
        if(bijiao(a[x].shu,b))break; 
        memcpy(ans,b,sizeof(ans));
    } 
    memcpy(ans1[a[x].o],ans,sizeof(ans1[a[x].o]));
    tot=l;   
}
int main(){
    scanf("%d",&t);
    fo(j,1,t){
        scanf("%s",s+1);
        tt=strlen(s+1);
        a[j].shu[0]=tt;
        a[j].o=j;
        fo(i,1,tt)a[j].shu[tt-i+1]=s[i]-'0';
    }
    sort(a+1,a+1+t,cmp);
    n=1000000;
    fo(i,2,trunc(sqrt(n))){
        if(!bz[i]){
            fo(j,2,n/i){
                bz[i*j]=1;
            }
        }
    }
    fo(i,2,n)if(!bz[i])zhi[++zhi[0]]=i;
    tot=1;ans[0]=ans[1]=1;
    fo(i,1,t){work(i);
        work(i);
    }
    fo(i,1,t){
        fod(j,ans1[i][0],1)printf("%d",ans1[i][j]);
        printf("\n");
    }
}

作者:zsjzliziyang
QQ:1634151125
转载及修改请注明
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/81366197

你可能感兴趣的:(题目,高精度,数学)