HDU 3988(数论)

本文介绍了一个算法挑战问题,通过质因子分解求解特定数学问题。输入包含多个测试用例,每个用例由两个长整数N和K组成。输出针对每个测试用例的解决方案,如果答案超过特定界限,则输出“inf”。文章提供了完整的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

iSea is tired of writing the story of Harry Potter, so, lucky you, solving the following problem is enough. 

Input

The first line contains a single integer T, indicating the number of test cases. 
Each test case contains two integers, N and K. 

Technical Specification 

1. 1 <= T <= 500 
2. 1 <= K <= 1 000 000 000 000 00 
3. 1 <= N <= 1 000 000 000 000 000 000 

Output

For each test case, output the case number first, then the answer, if the answer is bigger than 9 223 372 036 854 775 807, output “inf” (without quote).

Sample Input

2
2 2
10 10
Sample Output

Case 1: 1
Case 2: 2
题目分析:我们对k进行质因子分解,保存种类和对应的指数(factor[i][0]种类,factor[i][1]个数),我们也相应的求出N!中factor[i][0]的个数a,则ans=min(ans,a/factor[i][1]);

当k为1时则为inf

代码如下:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define ll  long long
using namespace std;

const int maxn=1e7+100;
int prime[maxn],cnt;
bool vis[maxn];

void get_prime()//素数打表
{
    memset (vis,true,sizeof (vis));
    vis[1]=false;
    for (int i=2;i<maxn;i++) {
        if (vis[i]) prime[cnt++]=i;
        for (int j=0;j<cnt&&i*prime[j]<maxn;j++) {
            vis[i*prime[j]]=false;
            if (i%prime[j]==0) break;
        }
    }
}
ll factor[1000][2],fcnt;
void get_factor(ll m)//求质因子
{
    memset (factor,0,sizeof (factor));
    fcnt=0;
    for (int i=0;i<cnt&&(ll) (prime[i]*prime[i])<=m;i++) {
        if (m%prime[i]==0) {
            factor[fcnt][0]=prime[i];
            while (m%prime[i]==0) {
                factor[fcnt][1]++;
                m=m/prime[i];
            }
            fcnt++;
        }
    }
    if (m!=1) {
        factor[fcnt][0]=m;
        factor[fcnt][1]=1;
        fcnt++;
    }
}
ll solve(ll m,ll k)//求m!中因子k的个数
{
    if (m/k==0) return 0;
    else return m/k+solve(m/k,k);
}
int main()
{
    int t,icase=1;
    get_prime();
    scanf("%d",&t);
    while (t--) {
        ll n,k;
        scanf("%lld%lld",&n,&k);
        if (k==1) {
            printf("Case %d: inf\n",icase++);
            continue;
        }
        get_factor(k);
        ll ans=1e18;
        for (int i=0;i<fcnt;i++) {
            ans=min(ans,solve(n,factor[i][0])/factor[i][1]);
        }
        printf("Case %d: %lld\n",icase++,ans);
    }
    return 0;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值