n!%k^i==0

n!%k^i==0

TimeLimit:5000MS  MemoryLimit:65536KB
64-bit integer IO format: %I64d
Problem Description
给你n和k,求最大的i 使得n!%k^i==0
Input
第一行是一个t表测试数据的组数 
每组测试数据包含2个数n和k 
1 <= T <= 500 
1 <= K <= 1 000 000 000 000 00 
1 <= N <= 1 000 000 000 000 000 000 
Output
每个测试数据先输出case数,然后输出答案。如果答案超过9 223 372 036 854 775 807 则输出“inf”
SampleInput
2
2 2
10 10
SampleOutput
Case 1: 1
Case 2: 2
被这题坑了好几次。 
注意点:
1、 由于 k 的 开方有一千万。 就是说, 得打表一千万以内的所有素数, 才60+万而已。在500次循环中, oj上有明显的用时。起码没打表的时候, 超时了
2、 int 整型相乘, 注意可能超出 int 范围, 超出范围, 是不会自动转换成 long long 型的。 所以得注意 类型 的 显式转换。
 
计算 n! 中 有几个 i 相乘, 有 递推 可求。详见代码。
 
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int all = (1e7)+1000;
bool test[ all ];
int con[ 700000 ], spot;
ll t, numk, numn, tmpk, tmpn, cnt, k, n;
void make()
{
    for( int i=2; i*i <= all; ++ i ){
        if( test[ i*i ] == true ){
            continue;
        }

        for( int j=i; i*j <= all; ++ j ){
            test[ i*j ] = true;
        }
    }
    for( int i=2; i <= all; ++ i ){
        if( ! test[ i ] ){
            con[ spot ++ ] = i;
        }
    }
}

int main(void)
{
    spot = 0;
    make();

    scanf( "%d", &t );
    for( int i=1; i <= t; ++ i ){
        scanf( "%I64d%I64d", &n, &k );
        printf( "Case %d: ", i );
        cnt = 9223372036854775807;
        if( k == 1 ){
            puts( "inf" );
            continue;
        }

        // 利用 k 的缩小, 可以缩短计算量
        // 注意 int 类型的范围, 这里需要进行 显式转换 成 long long 类型, 否则会溢出
        for( int j=0; (ll)con[j]*con[j] <= k; ++ j ){
            if( k % con[j] == 0 ){
                numk = 0;
                while( k % con[j] == 0 ){
                    k /= con[j];
                    ++ numk;
                }

                // 计算 n!中 含有几个 con[j] 相乘
                numn = 0;
                tmpn = n;
                while( tmpn ){
                    tmpn /= con[j];
                    numn += tmpn;
                }
                cnt = cnt < numn/numk ? cnt : numn/numk;
            }
        }

        // 存在当 con[j]*con[j] > k, 而又 k != 1 时, 所需要的计算
        if( k != 1 ){
            numn = 0;
            tmpn = n;
            while( tmpn ){
                tmpn /= k;
                numn += tmpn;
            }
            cnt = cnt < numn ? cnt : numn;
        }
        printf( "%I64d\n", cnt );
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/seana/p/5263417.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值