【JZOJ B组】【NOIP2013模拟】Heaven Cow与God Bull

37 篇文章 0 订阅

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。

思路

首先,我们知道phi(n)=n*(1-1/p1)(1-1/p2)…(1-1/pk)
那么,n/phi(n)=(p1/p1-1)(p2/p2-1)…(pn/pn-1)

明显,就是求质数相乘,满足ans< n

需要高精度压位

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
const long long mod=100000000000;
using namespace std;
long long b[6500][2500],z[6500],t,n,m,a[2500];
char s[100000];
int times(long long x,long long y,long value)
{
    long i,j,k,l;
    for(i=1; i<=b[x][0]; i++)
    {
        b[y][i]+=b[x][i]*value;
        b[y][i+1]+=b[y][i]/mod;
        b[y][i]%=mod;
    }
    b[y][0]=b[x][0];
    if(b[y][b[y][0]+1]>0) b[y][0]++;
}
int check(long long a[2500],long long b[2500])
{
    if(b[0]>a[0]) return 1;else if(b[0]<a[0]) return 0; else
    {
        for(long long i=b[0]; i>=1; i--)
        {
            if(b[i]>a[i]) return 1;else if(b[i]<a[i]) return 0;
        }
    }
    return 0;
}
int main()
{
    scanf("%lld",&t);
    long long i,j,k,l,x,y;
    for(i=2; i<=60000; i++)
    {
        bool q=1;
        for(j=2; j<=sqrt(i); j++)
        {
            if(!(i%j)) q=0;
        }
        if(q)
        {
            z[++z[0]]=i;
        }
    }
    b[0][0]=1;
    b[0][1]=1;
    for(i=1; i<=z[0]; i++)
    {
        times(i-1,i,z[i]);
    }
    while(t--)
    {
        scanf("%s",s);
        a[0]=0;
        k=0;
        int len=strlen(s);
        l=1;
        for(i=1; i<=len; i++)
        {
            k=k+(s[len-i]-48)*l;
            l*=10;
            if(l==mod)
            {
                a[++a[0]]=k;
                l=1;
                k=0;
            }
        }
        if(k) a[++a[0]]=k;
        for(i=1; i<=z[0]; i++)
        {
            if(check(a,b[i]))
            {
                for(j=b[i-1][0];j>=1;j--)
                {
                    if(j!=b[i-1][0]) printf("%011lld",b[i-1][j]);else printf("%lld",b[i-1][j]);
                }
                break;
            }
        }
        printf("\n");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值