1. 程式人生 > >[HDU 3944] DP?組合數 Lucas定理

[HDU 3944] DP?組合數 Lucas定理

DP?

Time Limit: 3000ms Memory Limit: 128MB

Description

啊哈
Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0,1,2,…and the column from left to right 0,1,2,….If using C(n,k) represents the number of row n, column k. The Yang Hui Triangle has a regular pattern as follows.
C(n,0)=C(n,n)=1 (n ≥ 0)
C(n,k)=C(n-1,k-1)+C(n-1,k) (

0<k<n)
Write a program that calculates the minimum sum of numbers passed on a route that starts at the top and ends at row n, column k. Each step can go either straight down or diagonally down to the right like figure 2.
As the answer may be very large, you only need to output the answer mod p which is a prime.

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.

Output

For every test case, you should output “Case #C: ” first, where C indicates the case number and starts at 1.Then output the minimum sum mod p.

Sample Input

1 1 2
4 2 7

Sample Output

Case #1: 0
Case #2: 5

題目大意

給多個詢問,每次問從楊輝三角的頂點走到(i,j)的路徑上點的最小和%p的值,每次只能向下或右下走。

解題報告

讓j*2小於i,否然C(i,j) = C(i, i-j)
然後發現肯定是先向下走再向右下走最優。
然後又發現C(i,j)+C(i-1,j-1)+….=C(i+1,j), 這個東西可以畫一個楊輝三角出來然後用遞推公式來意識上[滑稽]證明一下。
答案現在等於(n-m)+C(i+1,j)
發現i和j高達10^9那麼普通的階乘+逆元肯定是搞不出來的然後看到模數p很小隻有10^4就可以使用Lucas(盧卡斯)定理來搞啦^.^
Lucas 定理:

這裡寫圖片描述
這裡寫圖片描述
就有
這裡寫圖片描述
這種組合一定存在應為這相當於把m,n以p進製表示

現在就可以遞迴地求組合數啦, %p之後的組合數直接階乘+逆元就可以啦
在這裡看用快速冪求逆元
擴充套件歐幾里得也可以並且更快,但是我比較懶嘛。。
還有注意計算組合數一定一定一定要判斷返回值為0的情況啊!

程式碼

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>

int P;

int advPow (int a, int b) {
    if(a == 0) return 0;
    int ret = 1;
    while(b) {
        if(b&1) ret *= a, ret %= P;
        a *= a;
        a %= P;
        b >>= 1;
    }
    return ret;
}
int * fac;
int stor[1500][11000], tot;
inline int caltC (int n, int m) {
    if(n<m) return 0;
    if(n == m || m == 0) return 1;
    if(n == m+1 || m == 1) return n;
    return (fac[n]*advPow(fac[m]*fac[n-m]%P, P-2)%P) % P;
}

int Lucas (int n, int m) {
    if(n<P && m<P) return caltC(n, m);
    return caltC(n%P, m%P)*Lucas(n/P, m/P)%P;
}
int pos[11000];
int main () {
    int n, m, cas = 0;
    while(~scanf("%d%d%d", &n, &m, &P)) {
        if(!pos[P]) {
            pos[P] = ++tot;
            fac = stor[tot];
            fac[1] = 1;
            for(int i = 2; i<=P; i++)
                fac[i] = (fac[i-1]*i)%P;
        } else fac = stor[pos[P]];
        if(m*2>n) m = n-m;
        printf("Case #%d: %d\n", ++cas, ((n-m)+Lucas(n+1, m)) % P);
    }
}

相關推薦

[HDU 3944] DP合數 Lucas定理

DP? Time Limit: 3000ms Memory Limit: 128MB Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bot

合數+Lucas定理】2017多校訓練七 HDU 6129 Just do it

clu sca def opened == cnblogs long 合數 color http://acm.hdu.edu.cn/showproblem.php?pid=6129 【題意】 對於一個長度為n的序列a,我們可以計算b[i]=a1^a2^......^ai,

hdu 3037 費馬小定理+逆元求合數+Lucas定理

void log 打表 數學 mod turn ret iostream toc 組合數學推推推最後,推得要求C(n+m,m)%p 其中n,m小於10^9,p小於1^5 用Lucas定理求(Lucas定理求nm較大時的組合數) 因為p數據較小可以直接階乘打表求逆元

HDU 3037 Saving Beans (Lucas定理求大數合數

#include <iostream> #include <cstdio> using namespace std; typedef long long ll; const

HDU 3944 DP? 【合數取模+階乘預處理】

題意:從楊輝三角頂部走到的第n行第m列有很多種走法,求出這些走法中所經過的數之和的最小值。 首先稍加分析得出答案的組合表示式 C(n+1,m+1,p)+m (mod p)  這是在2m>n時的結

Rikka with Subset HDU - 6092 (DP+合數

namespace col calculate tint 組合數 XML res while restore As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gi

lightoj 1095 - Arrange the Numbers(dp+合數

鏈接 簡單 turn amp using ace ring ++ ber 題目鏈接:http://www.lightoj.com/volume_showproblem.php?problem=1095 題解:其實是一道簡單的組合數只要推導一下錯排就行了。在這裏就推導

[樹形dp][合數] JZOJ P1794 保鏢排隊

scrip 方案 sca 原理 數據 clear 排列 排隊 ios Description 【問題背景】  教主LHX作為知名人物,時刻會有恐怖分子威脅他的生命。於是教主雇傭了一些保鏢來保障他的人生安全。【題目描述】  教主一共雇傭了N個保鏢,編號為1~N。每個保鏢

BZOJ 2425 [HAOI2010]計數:數位dp + 合數

scanf ++ www. efi 題意 lin namespace pac strlen 題目鏈接:http://www.lydsy.com/JudgeOnline/problem.php?id=2425 題意:   給你一個數字n,長度不超過50。   你可以將這

LightOJ - 1246 Colorful Board(DP+合數

show 得到 需要 lld http ans while fine template http://lightoj.com/volume_showproblem.php?problem=1246 題意 有個(M+1)*(N+1)的棋盤,用k種顏色給它塗色,要求曼哈頓距

Wall Painting HDU - 4810(合數異或和)

Ms.Fang loves painting very much. She paints GFW(Great Funny Wall) every day. Every day before painting, she produces a wonderful color of pigments

[bzoj4737][數論][DP]合數問題

Description 組合數C(n,m)表示的是從n個物品中選出m個物品的方案數。舉個例子,從(1,2,3)三個物品中選擇兩個物品可以有( 1,2),(1,3),(2,3)這三種選擇方法。根據組合數的定義,我們可以給出計算組合數C(n,m)的一般公式:

【AtCoder2000】Leftmost Ball (DP+合數

題意 Snuke喜歡五顏六色的球。他總共有N×K個球,有N種顏色,每種顏色的球有K個。顏色編號為1到N。他將按照任意順序排列所有球。然後,對於每種顏色,他將該顏色的最左邊的球塗成顏色0,顏色0不同於N

CodeForces - 285E: Positions in Permutations(DP+合數+容斥)

NPU ner each i+1 -- -c put ont sin Permutation p is an ordered set of integers p1,  p2,  ...,  

各種逆元求法 合數取模 comb (合數 Lucas

組合數取模(comb) 【問題描述】 計算C(m,n)mod 9901的值 【輸入格式】 從檔案comb.in中輸入資料。 輸入的第一行包含兩個整數,m和n 【輸出格式】 輸出到檔案comb.out中。 輸出一行,一個整數 【樣例輸入】 2

hdu 5698 求合數(逆元+階乘 遞推公式

分析向格子裡填數發現,是左斜的楊輝三角,發現規律,其實就是求C(n+m-4,m-2)的組合數 求組合數用逆元+階乘(遞推) #include <iostream> #include <cstdio> #define ll long long

C. On the Bench(dp + 合數

題意 一個長度為 \(n\) 的序列 \(A\) ,定義一個 \(1\) 到 \(n\) 的排列 \(p\) 是合法的,當且僅當 \(\forall i \in [1, n − 1], A_{p_i} × A_{p_i+1}\) 不是完全平方數。 求有多少合法的排列,對 \(10^9 + 7\) 取模。 \(

BZOJ4550 小奇的博弈 【Nimk遊戲 + dp + 合數

題目 這個遊戲是在一個1*n的棋盤上進行的,棋盤上有k個棋子,一半是黑色,一半是白色。最左邊是白色棋子,最右邊 是黑色棋子,相鄰的棋子顏色不同。 小奇可以移動白色棋子,提比可以移動黑色的棋子,它們每次操作可以移動1到d個棋子。每當移動某一個棋子時,

百度之星 初賽2 瞬間轉移 HDU 5698 (合數+逆元)

大意:有一個無限大的矩形,初始時你在左上角(即第一行第一列),每次你都可以選擇一個右下方格子,並瞬移過去(如從下圖中的紅色格子能直接瞬移到藍色格子),求到第n行第m列的格子有幾種方案,答案對10000

hdu5396(區間dp+合數)

題意:給一個表示式,求所有的計算順序產生的結果總和並取餘 程式碼: #include <stdio.h> #include <stdlib.h> #include <s