zoukankan      html  css  js  c++  java
  • HDU 3944 DP? [Lucas定理 诡异的预处理]

    DP?

    Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 128000/128000 K (Java/Others)
    Total Submission(s): 3126    Accepted Submission(s): 978

    Problem Description
    Input
    Input to the problem will consists of series of up to 100000 data sets. For each data there is a line contains three integers n, k(0<=k<=n<10^9) p(p<10^4 and p is a prime) . Input is terminated by end-of-file.
     

    数据范围诡异系列~
    题意:杨辉三角可以往左或者往右走走到$(n,k)$的最小权值和

    显然每一层都要取一个权值,并且越往外权值越小,当然是尽量往外最好啦
    对称,k>n/2时变成n-k
    如果从$(n,k)$向左斜着上去,结果就是
    ${nchoose k}+{n-1choose k-1}+...+{n-kchoose 0}+n-k$
    然后用组合数递推式合并,就是
    ${n+1choose k}+n-k$
     
    问题在于T太大啦,以致于<10000的质数远比T小,我们预处理模所有质数意义下的阶乘吧!
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int N=10007;
    int n,m,P;
    bool notp[N];
    int p[N];
    void sieve(int n){
        for(int i=2;i<=n;i++){
            if(!notp[i]) p[++p[0]]=i;
            for(int j=1;j<=p[0]&&i*p[j]<=n;j++){
                notp[i*p[j]]=1;
                if(i%p[j]==0) break;
            }
        }
    }
    int fac[N][1300],mp[N],pnum;
    void ini(int n){
        sieve(n);
        for(int j=1;j<=p[0];j++){
            int x=p[j];mp[x]=j;
            fac[0][j]=1;
            for(int i=1;i<=n;i++) fac[i][j]=fac[i-1][j]*i%x;
        }
    }
    int Pow(int a,int b){
        int re=1;
        for(;b;b>>=1,a=a*a%P)
            if(b&1) re=re*a%P;
        return re;
    }
    int Inv(int a){return Pow(a,P-2);}
    int C(int n,int m){
        if(n<m) return 0;
        return fac[n][pnum]*Inv(fac[m][pnum])%P*Inv(fac[n-m][pnum])%P;
    }
    int Lucas(int n,int m){
        if(n<m) return 0;
        int re=1;
        for(;m;n/=P,m/=P) re=re*C(n%P,m%P)%P;
        return re;
    }
    int main(){
        freopen("in","r",stdin);
        int cas=0;
        ini(10000);
        while(scanf("%d%d%d",&n,&m,&P)!=EOF){
            if(m>n/2) m=n-m;
            pnum=mp[P];
            printf("Case #%d: %d
    ",++cas,(Lucas(n+1,m)+n-m)%P);
        }
    }
     
     
     
     
     
     
  • 相关阅读:
    winform最大化后不遮挡任务栏
    TabControl控件重绘
    EXT gridPanel 添加图片
    好记性不如烂笔头——double
    好记性不如烂笔头——datagridview相关
    datagridview合并相同单元格
    datagridview问题
    Linux折腾记
    TSC打印机使用教程终极版
    在线直播流测试地址
  • 原文地址:https://www.cnblogs.com/candy99/p/6403242.html
Copyright © 2011-2022 走看看