首页 > 其他 > 详细

【JZOJ5164】【NOIP2017模拟6.25】小A做CF

时间:2020-03-08 19:56:36      阅读:41      评论:0      收藏:0      [点我收藏+]

题目大意:

在一个 \(n \times n\) 的棋盘上,有 \(n\) 个障碍物,它们两两不同行不同列,如果再放 \(n\) 个棋子在棋盘上,条件也是两两不同行不同列且不能放在障碍物上,求一共有多少种方案。

正文:

首先来举个例子:

0 1 0
1 0 0
0 0 1

因为它们两两不同列,也就是说每列都有一个,那么干脆直接用一个数列 \(a\) 代替它的位置。\(a_i\) 表示第 \(i\) 列的障碍物的行数。那么上面的例子可以这么表示 \(a=\{2,1,3\}\)

剩下的任务就是求方案数。如果第 \(i\) 列的棋子不能放在 \(a_i\) 上且放的行数不与其它棋子的行数相同,我们就可以发现,这是一个错位排列。所以跟这个矩阵没什么关系,关键点是在 \(n\) 上,可以不读入矩阵。

直接求错位排列,\(\texttt{60}\) 分,因为 \(n \leq 200\),所以正解要高精度运算。

代码:

void opt(int b[], int c[], int d, int e)
{
    memset(a, 0, sizeof(a));
    int g, v;
        g = v = 0;
    for (int i = 1; i <= max(b[0], c[0]) + 10; i++)
    {
        g = b[i] + c[i] + v;
        v = g / 10;
        a[i] = g % 10;
    }
    for(a[0] = max(b[0], c[0]) + 10; !a[a[0]]; a[0]--);
    g = v = 0;
    for (int i = 1; i <= a[0] + 10; i++)
    {
        g = a[i] * d + v;
        v = g / 10;
        f[e][i] = g % 10;
    } 
    for(f[e][0] = a[0] + 10; !f[e][f[e][0]]; f[e][0]--);
}

int main()
{
    scanf("%d", &n);
        for(int i = 1, j; i <= n * n; i++) scanf ("%d", &j);
    f[2][1] = f[2][0] = 1;
    for(int i = 3; i <= n; i++) 
        opt(f[i - 1], f[i - 2], i - 1, i);
    for (int i = f[n][0]; i >= 1; --i) printf("%d", f[n][i]);
}

【JZOJ5164】【NOIP2017模拟6.25】小A做CF

原文:https://www.cnblogs.com/GJY-JURUO/p/12444331.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!