2019湖南省赛 组合数(int128)

组合数
给出 n n k k ,求 min n ! k ! ( n k ) ! , 1 0 18 \min{\frac{n!}{k! (n - k)!}, 10^{18}} 的值。

其中 n ! = 1 × 2 × × n n! = 1 \times 2 \times \cdot \times n 表示 n n 的阶乘。

输入格式
输入文件包含多组数据,请处理到文件结束。

每组数据包含两个整数 n n k k .

0 k n 1 0 9 0 \leq k \leq n \leq 10^9
至多 1 0 5 10^5 组数据。
输出格式
对于每组数据,输出一个整数,表示所求的值。

思路:
__int128练习题

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;
const int maxn = 1e3 + 7;
const ll MAX = 1e18;
ll C[maxn][maxn];

void init()
{
    C[1][0] = C[1][1] = 1;
    for (int i = 2; i < maxn; i++){
        C[i][0] = 1;
        for (int j = 1; j < maxn; j++)
        {
            if(C[i - 1][j] < 0 || C[i - 1][j - 1] < 0)
                C[i][j] = -1;
            else
                C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]);
        }
    }
}

ll solve(ll n,ll k)
{
    __int128 tmp = 1,num = 1;
    for(int i = 1;i <= k;i++)
    {
        tmp *= n;
        n--;
        num *= i;
    }
    tmp /= num;
    if(tmp >= MAX)
        return -1;
    ll ans = tmp;
    return ans;
}

int main()
{
    init();
    ll n,k;
    while(~scanf("%lld%lld",&n,&k))
    {
        if(n >= 1000)
        {
            if(k > 10)
            {
                printf("%lld\n",MAX);
            }
            else
            {
                ll tmp = solve(n,k);
                if(tmp > MAX || tmp <= 0)
                {
                    printf("%lld\n",MAX);
                }
                else
                    printf("%lld\n",tmp);
            }
        }
        else if(C[n][k] >= MAX || C[n][k] <= 0)
        {
            printf("%lld\n",MAX);
        }
        else printf("%lld\n",C[n][k]);
    }
    return 0;
}

发布了756 篇原创文章 · 获赞 27 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/104642135