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

本文探讨了一种在中国象棋中摆放最多数量的車的方法,并确保它们不会互相攻击。通过数学组合的方式,给出了求解特定棋盘大小下摆放車的最大数量及方案数的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值