[BZOJ2227][Zjoi2011][找规律][排列组合][数学]看电影(movie)

本文介绍了一种处理大数运算及约分的方法,并通过一个具体的数学问题展示了如何使用C++实现大数的加减乘除及约分操作。通过枚举因子的方式实现了分子分母的有效约分。

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

首先数据很小……可以打表……找规律

找出来是 (k+1)n1(kn+1)kn

证明可以看这篇

我的约分的方法比较奇怪,因为只有200以下的因子,就暴力枚举1~200,分子分母能同时除就除掉,当初是从Manchery那看到的,感觉打起来要方便一点……

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

using namespace std;

int n,k,t;
int p[210],c[210];

struct Int{
    int a[1010],sz;
    #define base 100000
    Int(int x=0){ 
        memset(a,0,sizeof(a)); sz=0;
        while(x)a[++sz]=x%base,x/=base; 
    }
    int &operator [](int x){ return a[x]; }
    inline bool empty(){
        return sz==1&&a[1]==0;
    }
    friend Int operator +(Int A,Int B){
        Int C; C.sz=A.sz+B.sz;
        if(B.empty()) return A;
        if(A.empty()) return B;
        for(int i=1;i<=C.sz;i++) C[i]=A[i]+B[i];
        for(int i=1;i<=C.sz;i++)
            if(C[i]>=base){C[i+1]+=C[i]/base,C[i]%=base; if(i==C.sz)C.sz++;}
        return C;
    }
    friend Int operator *(Int A,Int B){
        Int C; C.sz=A.sz+B.sz-1;
        if(B.empty()) return B;
        for(int i=1;i<=A.sz;i++)
            for(int j=1;j<=B.sz;j++)
            C[i+j-1]+=A[i]*B[j];
        for(int i=1;i<=C.sz;i++)
            if(C[i]>=base){C[i+1]+=C[i]/base,C[i]%=base; if(i==C.sz)C.sz++;}
        return C;
    }
    friend Int operator -(Int A,Int B){
        for(int i=1;i<=B.sz;i++) A[i]-=B[i];
        for(int i=1;i<=A.sz;i++)
            if(A[i]<0) A[i]+=base,A[i+1]--;
        while(!A[A.sz]&&A.sz) A.sz--;
        if(!A.sz) A.sz++;
        return A;
    }
    friend Int operator /(Int A,int B){
        int x=0;
        for(int i=A.sz;i;i--){
            int t=(A[i]+x*base)%B;
            A[i]=(A[i]+x*base)/B;
            x=t;
        }
        while(!A[A.sz]&&A.sz) A.sz--;
        return A;
    }
    friend Int operator %(Int A,int B){
        return A-(A/B)*B;
    }
    Int &operator *=(int B){ *this=*this*B; return *this; }
    Int &operator /=(int B){ *this=*this/B; return *this; }
    inline void print(){
        if(!sz) putchar(48);
        printf("%d",a[sz]);for(int i=sz-1;i;i--) printf("%05d",a[i]);
    }
};

inline void simplify(Int &A,Int &B){
    for(int i=2;i<=200;i++)
        while((A%i).empty()&&(B%i).empty()) A/=i,B/=i;
}

Int Ans,Ans1;

int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        if(k<n) { puts("0 1"); continue; }
        Ans=1; Ans1=1;
        for(int i=1;i<=n-1;i++) Ans*=k+1;
        for(int i=1;i<=n;i++) Ans1*=k;
        Ans*=k-n+1;
        simplify(Ans,Ans1);
        Ans.print(); putchar(' '); Ans1.print(); putchar('\n');
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值