BZOJ4563:[HAOI2016]放棋子——题解

探讨在一个N*N矩阵中,每行放置一枚棋子且避开障碍物的错排问题解决方案。利用高精度计算处理棋子放置的不同组合,确保每行每列仅有一枚棋子。

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

https://www.lydsy.com/JudgeOnline/problem.php?id=4563

给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少种方案。

假设最开始棋子都放在障碍上,然后将所有行压成一行,那么下面的问题就是有多少种方法使得棋子不放在自己原来的位置上并且不能与别的棋子重合?

这就是一个错排问题了,高精即可。

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=10005;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct Bignum{//必须定义在main之外
    int a[N],len;
    Bignum(){
    memset(a,0,sizeof(a));len=0;
    }
    void print(){
    for(int i=len-1;i>=0;i--)putchar(a[i]+'0');
    putchar('\n');
    }
    Bignum operator +(const Bignum &b)const{
    Bignum ans;ans.len=len;
    for(int i=0;i<ans.len;i++)ans.a[i]=a[i];
    for(int i=0;i<ans.len;i++){
        ans.a[i]+=b.a[i];
        if(ans.a[i]>9){
        ans.a[i]-=10;ans.a[i+1]++;
        if(i+1==ans.len)ans.len++;
        }
    }
    if(ans.len<b.len){
        for(int i=ans.len;i<b.len;i++)ans.a[i]=b.a[i];
        ans.len=b.len;
    }
    return ans;
    }
    Bignum operator *(const int &b)const{
    Bignum ans;ans.len=len;
    for(int i=0;i<ans.len;i++)ans.a[i]=a[i]*b;
    for(int i=0;i<ans.len;i++){
        if(ans.a[i]>9){
        ans.a[i+1]+=ans.a[i]/10;ans.a[i]%=10;
        if(i+1==ans.len)ans.len++;
        }
    }
    return ans;
    }
}d1,d2;
int n;
int main(){
    n=read();
    if(n==1){puts("0");return 0;}
    if(n==2){puts("1");return 0;}
    d1.a[0]=0;d1.len=1;
    d2.a[0]=1;d2.len=1;
    for(int i=3;i<=n;i++){
    Bignum ans=(d2+d1)*(i-1);
    swap(d1,d2);swap(d2,ans);
    }
    d2.print();
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

转载于:https://www.cnblogs.com/luyouqi233/p/9197744.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值