A.牛牛扔牌(双端队列)/B.疯狂过山车(最长上升子序列)/C.牛牛的棋盘(容斥原理)

A.牛牛扔牌(双端队列)
题目链接:https://ac.nowcoder.com/acm/contest/6219/A

分析:支持从牌顶拿出和牌底拿出,可以想到一个数据结构(双端队列),于是我们可以用STL的deque,或者自己写一个。

class Solution {
public:
	/**
	 *
	 * @param x string字符串 字符串从前到后分别是从上到下排列的n张扑克牌
	 * @return string字符串
	 */
	bool check(int x)
	{
		if (x < 2) return false;
		for (int i = 2; i <= x / i; ++i)
		{
			if (x % i == 0) return false;
		}
		return true;
	}
	string Orderofpoker(string x) {
		//string p;
		deque d;
		for (int i = 0; i < x.size(); i += 2)
		{
			string c;
			c += x[i];
			c += x[i + 1];
			d.push_back(c);
		}
		string res;
		int sz = d.size();
		while (sz)
		{
			string c;
			if (!check(sz))
			{
				c = d.back();
				d.pop_back();
				res += c;
			}
			else
			{
				c = d.front();
				d.pop_front();
				res += c;
			}
			--sz;
		}
		return res;
	}
};

B.疯狂过山车
题目链接:https://ac.nowcoder.com/acm/contest/6219/B

分析:经典的DP,从起点和终点求最长上升子序列,然后枚举分界点

const int N = 1000005;
int a[N], b[N];
class Solution {
public:
	/**
	 *
	 * @param n int整型
	 * @param num int整型vector
	 * @return int整型
	 */

	int getMaxLength(int n, vector& num) {
		for (int i = 0; i < num.size(); ++i)
		{
			a[i] = 1;
			if ((i - 1) >= 0)
			{
				if (num[i] > num[i - 1])
					a[i] = a[i - 1] + 1;
			}
		}
		for (int i = num.size() - 1; i >= 0; --i)
		{
			b[i] = 1;
			if ((i + 1) <= n - 1)
			{
				if (num[i] > num[i + 1])
					b[i] = b[i + 1] + 1;
			}
		}
		int res = 0;
		//枚举分界点
		for (int i = 0; i < n; ++i)
		{
			res = max(res, a[i] + b[i] - 1);
		}
		return res;
	}
};

C.牛牛的棋盘

题目链接:https://ac.nowcoder.com/acm/contest/6219/C

分析:经典的容斥原理题目,容斥原理可以查一下学一下。我们用二进制枚举所有的情况,我们的总方案是\(C_{n * m}^{k}\),其中含有不合法的情况。即第一行、最后一行、第一列、最后一列的不摆放棋子的情况要排除,我们可以用容斥原理去排除哪些不需要,哪些重复减了的情况要加回来。

const int N = 2005;
const int mod = 1e9 + 7;
using LL = long long;
int fact[N], infact[N];
class Solution {
public:
    /**
     *
     * @param n int整型
     * @param m int整型
     * @param k int整型
     * @return int整型
     */
    int qmi(int a, int k, int p)    // 快速幂模板
    {
        int res = 1;
        while (k)
        {
            if (k & 1) res = (LL)res * a % p;
            a = (LL)a * a % p;
            k >>= 1;
        }
        return res;
    }
 
    int C(int a, int b)
    {
        if(a < b) return 0;
        return (LL)fact[a] * infact[a - b] % mod * infact[b] % mod;
    }
 
    void init()
    {
        fact[0] = infact[0] = 1;
        for (int i = 1; i < N; i++)
        {
            fact[i] = (LL)fact[i - 1] * i % mod;
            infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
        }
    }
 
    int solve(int n, int m, int k) {
        init();
 
        if (k == 2) return 2;
        if (k < 2) return 0;
 
        int res = 0;
 
        for (int i = 0; i < 16; ++i)
        {
            int r = n, c = m;
            int cnt = 0;
            if ((i >> 3) & 1) --r, ++cnt;
            if ((i >> 2) & 1) --r, ++cnt;
            if ((i >> 1) & 1) --c, ++cnt;
            if ((i >> 0) & 1) --c, ++cnt;
            if(cnt & 1)
                res = ((LL)res - C(r * c, k) + mod) % mod;
            else
                res = ((LL)res + C(r * c, k)) % mod;
        }
        return res % mod;
    }
};

你可能感兴趣的:(A.牛牛扔牌(双端队列)/B.疯狂过山车(最长上升子序列)/C.牛牛的棋盘(容斥原理))