FZU 1753 Another Easy Problem 解题报告(素因子统计)

本文介绍了一道关于求解多个组合数方程最大模数的问题,并提供了详细的解题思路及C++实现代码。通过素数筛法与组合数性质分析,解决了输入方程组后求得满足条件的最大M值。

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

Problem 1753 Another Easy Problem

Accept: 400    Submit: 1804
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

小TT最近学习了高斯消元法解方程组,现在他的问题来了,如果是以下的方程,那么应该如何解呢?

C(n1,m1)==0 (mod M)

C(n2,m2)==0 (mod M)

C(n3,m3)==0 (mod M)

................

C(nk,mk)==0 (mod M)

小TT希望你告诉他满足条件的最大的M

其中C(i,j)表示组合数,例如C(5,2)=10,C(4,2)=6...

 Input

输入数据包括多组,每组数据的第一行是一个正整数T(1<=T<=150)表示接下来描述的T个方程

接下来T行,每行包括2个正整数ni,mi (1<=mi<=ni<=100000)

 Output

输出一行答案,表示满足方程组的最大M。

 Sample Input

3100 150 160 1

 Sample Output

10

 Source

FZU 2009 Summer Training IV--Number Theory


    解题报告: 个人觉得题目出的不是太严谨,没有给出结果的数据范围。如果输入数据是

    1

    100000 50000

    那么结果有7000+多位。这题的话unsigned long long 可以搞定。

    优化的地方是进行素数判断时,素数大于最小的n时就不用判断了。注意输出用I64u

    代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef unsigned long long LLU;

const int maxn = 100001;
int prime[maxn];
int primeNum;
bool h[maxn];

void calPrime()
{
    for(int i=2;i<maxn;i++) if(!h[i])
    {
        prime[primeNum++]=i;
        for(int j=i+i;j<maxn;j+=i) h[j]=true;
    }
}

int calN(int n, int k)
{
    int res=0;
    while(n>=k)
    {
        n/=k;
        res+=n;
    }
    return res;
}

LLU powLLU(LLU a, int b)
{
    LLU res=1;
    while(b)
    {
        if(b&1)
            res = res*a;
        a = a*a;
        b>>=1;
    }
    return res;
}

int num[155];
int kk[155];

void work(int n)
{
    int limit = maxn;
    for(int i=0;i<n;i++)
        scanf("%d%d", num+i, kk+i), limit=min(limit, num[i]);

    LLU ans=1;
    for(int i=0;prime[i]<=limit && i<primeNum;i++)
    {
        int t=maxn;
        for(int j=0;j<n;j++)
            t=min(t, calN(num[j], prime[i])-calN(kk[j], prime[i])-calN(num[j]-kk[j], prime[i]));

        if(t!=maxn)
            ans*=powLLU(prime[i], t);
    }
    printf("%I64u\n", ans);
}

int main()
{
    calPrime();

    int n;
    while(~scanf("%d", &n))
        work(n);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值