zoukankan      html  css  js  c++  java
  • LG 题解 CF1545B AquaMoon and Chess

    题目传送门

    更差的阅读体验

    Solution

    你拿到这个题后开始手模它这个操作。

    你发现,对于一个 11 移动的时候就相当于整体左移或者右移。

    我们假设让它右移,如果它右边是一个 0,那么它右移就相当于和这个 0 交换位置。如果它右边是一个 1实际并不能右移,但也可以看做它和这个 1 交换了一下位置。

    那不难看出,和 0 交换位置时会产生新的状态,和 1 交换位置时并不会产生新的状态。

    也不难看出,每一组 11 在整个序列中都是可以自由移动的。那么我们不妨将每个 11 都划分成一个整体,对于那些单独的 1 就直接扔掉。

    那么对于剩下的 110,显然可以随便安排他们的位置。

    设有 (x)11(y)0,总排列数位 ((x+y)!),因为有重复状态所以再除以 (x! y!),也就是说答案为 (inom{x+y}{x})

    直接预处理一个阶乘和逆元就可以 (mathcal O(1)) 计算了。

    至于 (x)(y) 从原串中暴力找就可以。

    Code

    /*
    Work by: Suzt_ilymtics
    Problem: 不知名屑题
    Knowledge: 垃圾算法
    Time: O(能过)
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define int long long
    #define orz cout<<"lkp AK IOI!"<<endl
    
    using namespace std;
    const int MAXN = 2e5+50;
    const int INF = 1e9+7;
    const int mod = 998244353;
    
    int T, n;
    int fac[MAXN], inv[MAXN];
    char s[MAXN];
    
    int read(){
        int s = 0, f = 0;
        char ch = getchar();
        while(!isdigit(ch))  f |= (ch == '-'), ch = getchar();
        while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
        return f ? -s : s;
    }
    
    void Init() {
        int M = 200000;
        fac[0] = fac[1] = inv[0] = inv[1] = 1;
        for(int i = 2; i <= M; ++i) {
            fac[i] = fac[i - 1] * i % mod;
            inv[i] = (mod - mod / i) * inv[mod % i] % mod;
        }
        for(int i = 2; i <= M; ++i) {
            inv[i] = inv[i - 1] * inv[i] % mod; 
        }
    }
    
    int C(int n, int m) {
        return fac[n] * inv[m] % mod * inv[n - m] % mod;
    }
    
    signed main()
    {
    	Init();
        T = read();
        while(T--) {
            n = read();
            cin >> s + 1;
            int y = 0, x = 0;
            for(int i = 1; i <= n; ++i) if(s[i] == '0') y++;
            for(int i = 2; i <= n; ++i) {
                if(s[i] == '1' && s[i - 1] == '1') {
                    x++, s[i] = s[i - 1] = '0';
                }
            }
            printf("%lld
    ", C(x + y, x));
        }
        return 0;
    }
    
    
  • 相关阅读:
    父进程pid和子进程pid的大小关系
    static 和extern关键字
    linux源码下载
    tar命令
    USB开发——内核USB驱动+libusb开发方法
    microchip PIC芯片使用方法
    android下4G上网卡
    Modem常用概念
    4G上网卡NIDS拨号之Rmnet驱动
    Uboot源码解析
  • 原文地址:https://www.cnblogs.com/Silymtics/p/solution-CF1545B.html
Copyright © 2011-2022 走看看