zoukankan      html  css  js  c++  java
  • [Swust OJ 247]--皇帝的新衣(组合数+Lucas定理)

    题目链接:http://acm.swust.edu.cn/problem/0247/

    Time limit(ms): 1000        Memory limit(kb): 65535
     
    Description
    在很久很久以前,有个臭美国王。一天,他得到了一件新衣,于是决定巡城看看老百姓的反应(囧)。于是他命令可怜的宰相数一下他有多少种巡城方案。 
    城市是一个N*M的矩形,(N+1)*(M+1)条街把城市分成了N*M块。国王从左下角出发,每次只能向右或向上走,右上角是终点。 
    请你帮帮可怜的宰相。
     
    Input
    每组测试数据有3个值 n m p(0< n <=1000000000,0 < m <=1000000000,p为质数且p<400). 
     
    Output
    多组测试数据 0 0 0结束。
    输出方案数 因为数据太大 请 mod p
     
    Sample Input
    2 3 97
    20 40 37
    0 0 0

    Sample Output
    10
    32

     
    Hint
    2009暑期ACM集训组队赛《一》 -- 剑问苍生
     
    解题思路:从左下角到右上角的方案数,那么(假设方阵大小n*m)
         (1)向上必须移动n格,向右必然移动m格
         (2)只需要以向上或向右移动为基准求C(n+m) n 或者C(n+m) m的组合数即可,好好想想为什么吧~~~~
            可以有一个优化组合数上面的去n,m中的较小值(组合数性质)
         (3)发现n,m<=1000000000那么在求组合数的时候肯定会直接爆掉,那怕是在求的过程中不断MOD 数p,
           那么我们以p的上限值为界求组合数,运用Lucas定理求解
     
    Lucas定理:(详情可以戳戳这里:http://www.cnblogs.com/zyxStar/p/4588362.html)

          Lucas定理用来求C(a,b)mod p的值,其中p为素数。
          数学表达式为:
          Lucas(a,b,q)=C(a%q,b%q)*Lucas(a/p,b/p,p);
          Lucas(a,0,q)=0;

          模运算与基本四则运算有些相似,但是除法例外。其规则如下:
          (a + b) % p = (a % p + b % p) % p (1)
          (a - b) % p = (a % p - b % p) % p (2)
          (a * b) % p = (a % p * b % p) % p (3)
          a ^ b % p = ((a % p)^b) % p (4)

    代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define maxn 405
     5 using namespace std;
     6 long long dp[maxn][maxn], n, m, p;
     7 long long Lucas(long long n, long long m, long long p){
     8     //Lucas定理
     9     if (n <= p && m <= p)
    10         return dp[n][m];
    11     else
    12         return (Lucas(n / p, m / p, p)*dp[n%p][m%p]) % p;
    13 }
    14 
    15 //杨辉三角求组合数
    16 void init(){
    17     int i, left, right;
    18     for (i = 1; i <= p; i++){
    19         dp[i][0] = dp[i][i] = 1;
    20         left = 1, right = i - 1;
    21         while (left <= right){
    22             dp[i][left] = (dp[i - 1][left - 1] + dp[i - 1][left]) % p;
    23             dp[i][right--] = dp[i][left++];//组合数性质dp[i][j]=dp[i][i-j];
    24         }
    25     }
    26 }
    27 int main(){
    28     while (cin >> n >> m >> p && n && m && p){
    29         memset(dp, 0, sizeof(dp));
    30         init();
    31         cout << Lucas(n + m, min(n, m), p) << endl;
    32     }
    33     return 0;
    34 }
    View Code

    乱搞的Java代码如下:

     1 import java.math.*;
     2 import java.io.*;
     3 import java.util.*;
     4 public class Main{
     5     static int DP[][] = new int[401][401];
     6     static int p;
     7     public static void main(String[] args)
     8     {
     9         Scanner cin = new Scanner(System.in);
    10         int a, b;
    11         while (cin.hasNext()){
    12             a = cin.nextInt();
    13             b = cin.nextInt();
    14             p = cin.nextInt();
    15             if (a == 0)
    16                 break;
    17             initDp();
    18             System.out.println(sloveRe(a + b, b > a ? a : b));
    19         }
    20     }
    21     private static void initDp(){
    22         int i, j;
    23         for (i = 0; i <= p; i++){
    24             DP[i][0] = 1;
    25         }
    26         for (i = 1; i <= p; i++){
    27             for (j = 1; j <= p; j++){
    28                 DP[i][j] = (DP[i - 1][j] + DP[i - 1][j - 1]) % p;
    29             }
    30         }
    31     }
    32     private static int sloveRe(int n, int m){
    33         if (n <= p&&m <= p)
    34             return DP[n][m];
    35         else
    36             return  (sloveRe(n / p, m / p)*DP[n%p][m%p]) % p;
    37     }
    38 }
    View Code
  • 相关阅读:
    hadoop 之 kafka 安装与 flume -> kafka 整合
    软考倒计时28天:项目一般管理
    HACMP5.4常用命令
    db2还原离线备份文件报错SQL2071N 提示“访问共享库出现错误”解决
    远程桌面不能拷贝文件的问题
    ubuntu设置开机启动命令行模式
    Rainmeter如何打开控制面板的小程序
    /var/adm/wtmp文件太大该怎么办?
    SQL1221N The Application Support Layer heap cannot be allocated. SQLSTATE=57011
    DB21019E An error occurred while accessing the directory "/root".
  • 原文地址:https://www.cnblogs.com/zyxStar/p/4587185.html
Copyright © 2011-2022 走看看