解码(改)

来源:互联网 发布:验证码js ajax demo 编辑:程序博客网 时间:2024/05/20 18:00

【题目描述】
从前有一只红色的云在天上非常愉快地飘,但是……
红云是一只十分好奇的生物(友情提示:生物考试的时候千万不能说云是生物,千万不能!),俗话说好奇心害死云,红云因为太好奇了所以被一个邪恶的地球人的陷阱困住了。
陷阱有一个神奇的出口,但需要输入正确的密码。红云不能理解地球人的思维所以并不知道怎么办。幸运的是它发现陷阱的旁边有一只DTZ,于是它用iPhone6威胁DTZ帮它解码。
DTZ通过神奇的途径得知了密码是这道题的答案:对于一个包含n个数的数列,每一位可以从1~m中选择一个数填上去,使得这个数列递增。该数列每一位的数字不能相同,求总共有几种不同的选择方法。将答案模23333便是密码。
然而DTZ非常尴尬地发现他解决不了这个问题因为数实在太大了,所以就把这个锅强行甩给了你。作为一个善良的地球人,请尽快解决这个问题,这样红云就会十分感激并用iPhone6威胁评测系统给你的考试分数加上100分。
【输入描述】
输入包含两个正整数n,m
【输出描述】
输出包含一个正整数表示密码
【样例输入】
3 3
【样例输出】
1

【数据范围】
对于10%的数据,n=m
对于100%的数据,1<=n<=1000, n<=m<=10000

作者思路:
一开始的思路:直接C(n,m)。可是要mod 23333,题目瞬间恶心!!!!这种思路不可行!!!!
正确思路:(方法一)杨辉三角。依题意可发现C(n,m)和杨辉三角一样。先蒙一下,结果对了!!!注意,这里最好用滚动数组,不然MLE!!!嘿嘿嘿!!!

代码:

const m_d=23333;var f:array[-1..2,-10..10050]of longint;    n,m,i,j:longint;begin  assign(input,'d.in');  assign(output,'d.out');  reset(input);  rewrite(output);  read(n,m);  f[0,0]:=1;  for i:=1 to m do    for j:=0 to i do      f[i mod 2,j]:=(f[(i+1)mod 2,j-1]+f[(i+1)mod 2,j])mod m_d;  write(f[m mod 2,n]);  close(input);  close(output);end.

(方法二)快速幂。用C(n,m)可以,只不过mod要用快速幂。(快速幂要记一下)
代码:

#include<stdio.h>#include<iostream>#include<algorithm>using namespace std;int a[10001],b[10001];int ksm(int x,int y){    int ans=1;    while(y)    {        if(y%2==1) ans=ans*x%23333;        x=x*x%23333;        y=y/2;    }}int main(){    //freopen("d.in","r",stdin);freopen("d.out","w",stdout);    int n,m;    scanf("%d%d\n",&n,&m);    a[0]=b[0]=1;    for (int i=1;i<=m;i++)    {        a[i]=a[i-1]*i%23333;        b[i]=ksm(a[i],23331);    }    printf("%d",a[m]*b[n]%23333*b[m-n]%23333);    return 0;}