hdoj 3641

#include<cstdio>
#include<cstring>
#define N 105
__int64 prim[N];
int c[N];
__int64 pp[N];
int k;
int index;
void fun()
{
 int i,j;
 k=0;
 for(i=0;i<N;i++)
  c[i]=1;
 for(i=2;i<N;i++)
  for(j=i+i;j<N;j+=i)
   c[j]=0;
 prim[k++]=2;
 for(i=3;i<N;i+=2)
  if(c[i])
     prim[k++]=i;
  
}
__int64 merge(__int64 n,__int64 m)// 数论知识,求n!中含m的ans次方
{
 __int64 ans=0;
 while(n)
 {
  ans+=n/m;
  n/=m;
 }
 return ans;
}
__int64 solve(__int64 mid)//比较<=index的素数是否都满足
{
 //为什么不用求大于index的数是否满足?????
 int tp,flag=1;
 for(int i=0;flag&&prim[i]<=index;i++)
 {
  tp=prim[i];
  if(pp[tp])
  {
   if(pp[tp]>merge(mid,tp))
   {
    flag=0;//flag=0代表mid!除不尽;
    break;
   }
  }
 }
 return flag;
}
__int64 search(__int64 h)
{
 __int64 l=0,mid;
 while(l<=h)
 {
  mid=(l+h)>>1;
  if(solve(mid))
   h=mid-1;
  else
   l=mid+1;
 }
return l;
}
int main()
{
 int n,t,x;
 int i,j;
 __int64 temp,cnt;
 __int64 a[N],b[N];
 fun();
 scanf("%d",&t);
 while(t--)
 {
  scanf("%d",&n);
  for(i=0;i<n;i++)
  {
   scanf("%I64d%I64d",a+i,b+i);
  }
  memset(pp,0,sizeof(pp));
  for(i=0;i<n;i++)
  {
   temp=a[i];
   for(j=0;prim[j]<=a[i]&&j<k;j++)//j<k的原因是当prim[j]<a[j]时可能j=k;后面已经没有了素数了;
   {
     cnt=0;
     x=prim[j];
     while(temp%x==0)
     {
      cnt++;
      temp/=x;
     }
     cnt*=b[i];
     pp[x]+=cnt;//pp[x]代表含有素数x的pp[x]的次方
   }
  }
  __int64 mx=0;
  __int64 tt;
  for(i=0;prim[i]<100&&i<k;i++)
  {
    temp=prim[i];
    tt=pp[temp]*temp;
    if(mx<tt)//找出本生和它的次方数乘积最大的素数mx!一定能除尽;其实当mx为最大__int64时,二分也不会超时!!!下面的另一个程序就是只有只一点不懂却少了一半的代码!!!!
    {
     mx=tt;
     index=temp;
    }
  }
  temp=search(mx);//以mx为上限的原因就是n!中含m的次方数的解法(上面merge函数)的原理;
  printf("%I64d/n",temp);
 }
return 0;
 
}

 

 

 

 

#include<stdio.h>
#include<string.h>
__int64
a[100];
int
b[30];
__int64
f(__int64 n,int i)//求n!有b[i]的次方数!
{
    if
(n==1||n==0)return 0;
    __int64
num=0;
    while
(n)
        num+=(n/=b[i]);
    return
num;
}

int
main()
{

    for
(int i=2,j=1;i<100;i++)
        if
(!a[i])
        {

            b[j++]=i;
            int
k=i,tmp=i;
            while
((k+=tmp)<100)a[k]=1;
        }

        int
t;
        scanf("%d",&t);
        while
(t--)
        {

            memset(a,0,sizeof(a));
            int
n,max=0,i,x;
            scanf("%d",&n);
            while
(n--)
            {

                __int64
y;
                scanf("%d%I64d",&x,&y);
                for
(i=1;x!=1;i++)
                    while
(!(x%b[i]))
                    {

                        a[b[i]]+=y;
                        x/=b[i];
                    }

                max=(max>b[i-1])?max:b[i-1];
            }

            __int64
num=1,numq=1;
            for
(i=1;i<26;i++)
            {

                if
(!a[b[i]])continue;
                __int64
tmp,tmp1=1,tmp2=1;
                    tmp2=tmp2<<63-1;
                    do

                       {

                           if
(tmp2-tmp1==1){num=tmp2;break;}
                           tmp=(tmp1+tmp2)/2;
                           if
(f(tmp,i)>=a[b[i]])tmp2=tmp;
                           else
tmp1=tmp;
                       }
while(1);
               numq=numq>num?numq:num;
            }

            if
(numq==1)numq=0;//w了几次就是没注意0!=1 T_T!
            printf("%I64d/n",numq);
        }

    return
0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值