• loj #2038. 「SHOI2015」超能粒子炮・改


    #2038. 「SHOI2015」超能粒子炮・改

     

    题目描述

    曾经发明了脑洞治疗仪与超能粒子炮的发明家 SHTSC 又公开了他的新发明:超能粒子炮・改——一种可以发射威力更加强大的粒子流的神秘装置。

    超能粒子炮・改相比超能粒子炮,在威力上有了本质的提升。它有两个参数 nnn、kkk,它会向每个编号为 000 到 kkk(包含两端)的位置 iii 发射威力为 Cinmod2333 的粒子流。

    现在 SHTSC 给出了他的超能粒子炮・改的参数,让你求出其发射的粒子流的威力之和除以 233323332333 所得的余数。

    输入格式

    第一行一个整数 ttt 表示数据组数。
    之后 ttt 行,每行两个整数 nnn、kkk,含义如题面描述。

    输出格式

    ttt 行,每行一个整数,表示其粒子流的威力之和模 233323332333 的值。

    样例

    样例输入

    3
    5 5
    10 7
    1145 14

    样例输出

    32
    968
    763

    数据范围与提示

    对于 10%10\%10% 的数据,t=1t = 1t=1,n,k≤1000n, k leq 1000n,k1000;
    对于 30%30\%30% 的数据,t=1t = 1t=1,n,k≤1000000n, k leq 1000000n,k1000000;
    对于 50%50\%50% 的数据,t=1t = 1t=1,n≤1018,k≤1000n leq 10^{18}, k leq 1000n1018​​,k1000;
    对于 70%70\%70% 的数据,t=100t = 100t=100,n,k≤1018n, k leq 10^{18}n,k1018​​;
    对于 100%100\%100% 的数据,t=100000t = 100000t=100000,n,k≤1018n, k leq 10^{18}n,k1018​​。

     

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 2333
    #define maxn 3010
    using namespace std;
    int T,fac[maxn],inv[maxn];
    long long n,k;
    int Pow(int x,int y){
        int res=1;
        while(y){
            if(y&1)res=1LL*res*x%mod;
            x=1LL*x*x%mod;
            y>>=1;
        }
        return res;
    }
    long long C(long long n,long long m){
        if(m>n)return 0;
        return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
    long long Lucas(long long n,long long m){
        if(m==0)return 1;
        return 1LL*C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;
    }
    int main(){
        scanf("%d",&T);
        fac[0]=inv[0]=1;
        for(int i=1;i<=3000;i++){
            fac[i]=1LL*fac[i-1]*i%mod;
            inv[i]=Pow(fac[i],mod-2);
        }
        int ans;
        while(T--){
            ans=0;
            cin>>n>>k;
            for(int i=0;i<=k;i++){
                ans+=Lucas(n,i);
                if(ans>=mod)ans-=mod;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    50分 Lucas定理
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int mod=2333;
    long long sum[2335][2335];
    long long Pow(long long x,long long k){
        int res=1;
        while(k){
            if(k&1)res=res*x%mod;
            x=x*x%mod;
            k>>=1;
        }
        return res;
    }
    long long fact[mod+10],inv[mod+10];
    void init(){
        fact[0]=1;
        inv[0]=1;
        for(int i=1;i<=mod;i++){
            fact[i]=fact[i-1]*i%mod;
            inv[i]=Pow(fact[i],mod-2);
        }
    }
    long long Lucas(long long n,long long m){
        long long a,b,res=1LL;
        while(n&&m){
            a=n%mod,b=m%mod;
            if(a<b)return 0LL;
            res=res*fact[a]%mod*inv[b]%mod*inv[a-b]%mod;
            n/=mod,m/=mod;
        }
        return res;
    }
    long long cal(long long n,long long k){
        if(k<mod&&n<mod)
            return sum[n][k];
        long long ans=0;
        ans+=Lucas(n/mod,k/mod)*sum[n%mod][k%mod]%mod;
        ans%=mod;
        if(k>=mod)
            ans+=cal(n/mod,k/mod-1)*sum[n%mod][mod-1]%mod;
        ans%=mod;
        return ans;
    }
    int main(){
        int T;
        init();
        for(int i=0;i<mod;i++){
            for(int j=0;j<=i;j++){
                sum[i][j]=Lucas(i,j);
            }
            for(int j=1;j<mod;j++){
                sum[i][j]+=sum[i][j-1];
                sum[i][j]%=mod;
            }
        }
        scanf("%d",&T);
        while(T--){
            long long k,n;
            scanf("%lld%lld",&n,&k);
            printf("%lld
    ",cal(n,k));
        }
        return 0;
    }
    100分 Lucas定理+式子推导
  • 相关阅读:
    2. Add Two Numbers
    1. Two Sum
    leetcode 213. 打家劫舍 II JAVA
    leetcode 48. 旋转图像 java
    leetcode 45. 跳跃游戏 II JAVA
    leetcode 42. 接雨水 JAVA
    40. 组合总和 II leetcode JAVA
    24. 两两交换链表中的节点 leetcode
    1002. 查找常用字符 leecode
    leetcode 23. 合并K个排序链表 JAVA
  • 原文地址:https://www.cnblogs.com/thmyl/p/8854073.html
Copyright © 2020-2023  润新知