[BZOJ]4807: 車 组合数学+高精度

来源:互联网 发布:深圳软件产业基地公司 编辑:程序博客网 时间:2024/06/05 09:52

Description

众所周知,車是中国象棋中最厉害的一子之一,它能吃到同一行或同一列中的其他棋子。車跟車显然不能在一起打起来,于是rly一天又借来了许多许多的車在棋盘上摆了起来……他想知道,在N×M的矩形方格中摆最多个数的車使其互不吃到的情况下方案数有几种。但是,由于上次摆炮摆得实在太累,他为了偷懒,打算增加一个条件:对于任何一个車A,如果有其他一个車B在它的上面(車B行号小于車A),那么車A必须在車B的右边(車A列号大于車B)。棋子都是相同的。

题解

一开始看错题了TAT
原来是要摆最多的车。。、
所以就是C(max(n,m),min(n,m))就好了。。
然后这题数据还有问题。。
不仅是前50位,还要删去前导0QAQ
把我调死了

#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>using namespace std;const int N=1000005;int n,m;int pri[N],cnt=0;//质数表?int tt[N];bool ok[N];//这个数是不是质数void In (int x,int y){    if (ok[x]==true) {tt[x]+=y;return ;}    for (int u=1;u<=cnt&&pri[u]*pri[u]<=x;u++)    {        if (x==1) return;        while (x%pri[u]==0)        {            tt[pri[u]]+=y;            x/=pri[u];        }    }    if (ok[x]==true) {tt[x]+=y;return ;}    if (x==1) return ;    ok[x]=true;    pri[++cnt]=x;tt[x]+=y;}int a[55],lalal;void Add (int x){    for (int u=1;u<=lalal;u++)        a[u]=a[u]*x;    for (int u=1;u<=lalal;u++)    {        if (a[u]>10)        {            a[u+1]+=(a[u]/10);            a[u]%=10;        }    }    lalal++;    for (;lalal<=53;lalal++)        if (a[lalal]>10)        {            a[lalal+1]+=(a[lalal]/10);            a[lalal]%=10;        }        else break;    if (lalal>53 )lalal=53;    a[54]=0;    while (lalal>1&&a[lalal]==0) lalal--;}int mymin (int x,int y){return x<y?x:y;}int main(){    memset(ok,false,sizeof(ok));    memset(tt,0,sizeof(tt));    scanf("%d%d",&n,&m);    if (n>m) swap(n,m);    cnt=0;    for (int u=2;u<=n;u++)        In(u,-1);    for (int u=1;u<=n;u++)        In(m-u+1,1);    lalal=1;a[1]=1;    for (int u=1;u<=cnt;u++)    {        while (tt[pri[u]]!=0)        {            Add(pri[u]);            tt[pri[u]]--;        }    }    for (int u=mymin(50,lalal);u>=1;u--)        printf("%d",a[u]);    return 0;}
阅读全文
0 0