• 2020.1.9考试总结


    T1
    数据范围很合适..
    第一档就是暴力枚举
    第二档就是数位DP
    第三档就是矩阵乘法
    丢一下学长的博客

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define LL long long
    using namespace std;
    LL n;
    const int mod = 1e9 + 7;
    struct ju 
    {
    	LL c[4][4];
    	friend ju operator *(const ju &a, const ju &b) 
    	{
    		ju c;
    		memset(c.c, 0, sizeof(c.c));
    		for (int i = 1; i <= 3; ++i)
    			for (int j = 1; j <= 3; ++j)
    				for (int k = 1; k <= 3; ++k)
    					c.c[i][j] += a.c[i][k] * b.c[k][j] % mod, c.c[i][j] %= mod;
    		return c;
    	}
    } base, ans;
    LL ksm(LL a, LL b, LL mod) 
    {
    	LL res = 1;
    	for (; b; b >>= 1, a = a * a % mod)
    		if (b & 1)res = res * a % mod;
    	return res;
    }
    ju ksm(ju a, LL b) 
    {
    	ju res;
    	memset(res.c, 0, sizeof(res.c));
    	for (int i = 1; i <= 3; ++i)res.c[i][i] = 1;
    	for (; b; b >>= 1, a = a * a)
    		if (b & 1)res = res * a;
    	return res;
    }
    int main() 
    {
    	freopen("number.in", "r", stdin);
    	freopen("number.out", "w", stdout);
    	cin >> n;
    	base.c[1][1] = 3; base.c[1][2] = 2; base.c[1][3] = 0;
    	base.c[2][1] = 1; base.c[2][2] = 3; base.c[2][3] = 1;
    	base.c[3][1] = 0; base.c[3][2] = 2; base.c[3][3] = 3;
    	ans .c[1][1] = 3;
    	ans .c[2][1] = 1;
    	ans .c[3][1] = 0;
    	ans = ksm(base, n - 1) * ans;
    	(((ans.c[1][1] -= ksm(2, n, mod) + ksm(4, n, mod) % mod) %= mod) += mod) %= mod;
    	ans.c[1][1] += ksm(3, n, mod);
    	cout << ans.c[1][1] % mod;
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    

    T2
    发现一个位置的值是奇数当且仅当 它所在的行加的次数+它所在的列加的次数 的和是奇数。
    当有x行加了奇数次,y列加了奇数次,那么奇数个数就是(n-x)y+x(m-y)
    枚举x,可以解方程得到y,特判一下(2xn&&xmk)的情况(化一化式子就知道了),贡献就是(displaystyle C_n^xC_m^yC_{frac{r-x}{2}+n-1}^{n-1}C_{frac{c-y}{2}+m-1}^{m-1})
    大力卡一卡边界就行了。

    #include<iostream>
    #include<cstdio>
    #define int long long
    #define LL long long
    #define DB double
    using namespace std;
    LL n, m, r, c, k, ans;
    const int N = 400010, M = 200000, mod = 1e9 + 7;
    LL jc[N], inv[N];
    inline int read() 
    {
    	int res = 0; char ch = getchar(); bool XX = false;
    	for (; !isdigit(ch); ch = getchar())(ch == '-') && (XX = true);
    	for (; isdigit(ch); ch = getchar())res = (res << 3) + (res << 1) + (ch ^ 48);
    	return XX ? -res : res;
    }
    LL ksm(LL a, LL b, LL mod) 
    {
    	LL res = 1;
    	for (; b; b >>= 1, a = a * a % mod)
    		if (b & 1)res = res * a % mod;
    	return res;
    }
    void YYCH() 
    {
    	jc[0] = jc[1] = inv[0] = inv[1] = 1;
    	for (int i = 2; i <= M; ++i)jc[i] = jc[i - 1] * i % mod;
    	inv[M] = ksm(jc[M], mod - 2, mod);
    	for (int i = M - 1; i >= 1; --i)inv[i] = inv[i + 1] * (i + 1) % mod;
    }
    LL C(LL n, LL m) {if (n < m)return 0; return jc[n] * inv[m] % mod * inv[n - m] % mod;}
    void suan(LL x, LL y) 
    {
    	if (((r - x) & 1) || ((c - y) & 1))return;
    	ans += C(n, x) * C(m, y) % mod * C(((r - x) >> 1) + n - 1, n - 1) % mod * C(((c - y) >> 1) + m - 1, m - 1) % mod, ans %= mod;
    }
    DB jue(DB x) {return x > 0 ? x : -x;}
    int zheng(DB x) 
    {
    	return jue(x - (int)x) < 1e-3;
    }
    signed main() 
    {
    	freopen("matrix.in", "r", stdin);
    	freopen("matrix.out", "w", stdout);
    	cin >> n >> m >> r >> c >> k;
    	YYCH();
    	for (int x = (r & 1); x <= n; x += 2) 
    	{
    		if (n == 2 * x) 
    		{
    			if (x * m == k) for (int y = (c & 1); y <= m; y += 2)suan(x, y);
    		} 
    		else 
    		{
    			DB y = (DB)(k - x * m) / (n - 2 * x);
    			if ((int)y < 0 || !zheng(y))continue;
    			suan(x, y);
    		}
    	}
    	cout << ans;
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    

    T3
    前置题目线段树做法
    首先离线...
    原来的题目限制的只有自己这个位置,现在变成了它及它前边的k个位置。
    线段树维护 区间取min,单点查询 即可。
    考场上没开大空间直接凉凉...
    好像这道题莫队跑得挺快的。

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #define lson (k<<1)
    #define rson ((k<<1)|1)
    #define LL long long
    #define DB double
    using namespace std;
    int n, m, q, k;
    const int N = 400010, inf = 1e9;
    int vis[N], a[N], ans[N], to[N][11], las[N], tr[N << 2], lz[N << 2];
    struct Ask {int l, r, ans, id;} Q[N];
    int my1(const Ask &a, const Ask &b) {return a.l < b.l;}
    int my2(const Ask &a, const Ask &b) {return a.id < b.id;}
    inline int read() 
    {
    	int res = 0; char ch = getchar(); bool XX = false;
    	for (; !isdigit(ch); ch = getchar())(ch == '-') && (XX = true);
    	for (; isdigit(ch); ch = getchar())res = (res << 3) + (res << 1) + (ch ^ 48);
    	return XX ? -res : res;
    }
    void Write(int x, int opt) 
    {
    	if (opt && !x)putchar('0');
    	if (!x)return; Write(x / 10, 0);
    	putchar((x - x / 10 * 10) + '0');
    }
    void build(int k, int l, int r) 
    {
    	lz[k] = inf;
    	if (l == r) 
    	{
    		tr[k] = ans[l];
    		return;
    	}
    	int mid = (l + r) >> 1;
    	build(lson, l, mid); build(rson, mid + 1, r);
    }
    inline void cd(int k) 
    {
    	lz[lson] = min(lz[lson], lz[k]); lz[rson] = min(lz[rson], lz[k]);
    	lz[k] = inf;
    }
    void change(int k, int l, int r, int x, int y, int v) 
    {
    	if (x <= l && r <= y) 
    	{
    		lz[k] = min(lz[k], v);
    		return;
    	}
    	if (lz[k] != inf)cd(k);
    	int mid = (l + r) >> 1;
    	if (x <= mid)change(lson, l, mid, x, y, v);
    	if (mid + 1 <= y)change(rson, mid + 1, r, x, y, v);
    }
    int ask(int k, int l, int r, int pos) 
    {
    	if (l == r) 
    	{
    		return min(lz[k], tr[k]);
    	}
    	if (lz[k] != inf)cd(k);
    	int mid = (l + r) >> 1;
    	if (pos <= mid)return ask(lson, l, mid, pos);
    	else return ask(rson, mid + 1, r, pos);
    }
    inline void solve2() 
    {
    	for (int i = 1; i <= q; ++i) 
    	{
    		Q[i].l = read(); Q[i].r = read(); Q[i].id = i;
    	}
    	sort(Q + 1, Q + 1 + q, my1);
    	int now = 1;
    	for (int i = 1; i <= m; ++i) 
    	{
    		for (int j = max(1, a[i] - k + 1); j <= a[i]; ++j) 
    		{
    			vis[j] = 1;
    			to[las[j]][a[las[j]] - j] = i;
    			las[j] = i;
    		}
    		while (vis[now])++now;
    		ans[i] = now;
    	}
    	for (int i = 1; i <= n; ++i)to[las[i]][a[las[i]] - i] = m + 1;
    	build(1, 1, m);
    	now = 1; int pos;
    	for (int i = 1; i <= m; ++i) 
    	{
    		while (Q[now].l == i) 
    		{
    			Q[now].ans = ask(1, 1, m, Q[now].r);
    			++now;
    		}
    		for (int j = max(1, a[i] - k + 1); j <= a[i]; ++j) 
    		{
    			pos = to[i][a[i] - j] - 1;
    			change(1, 1, m, i, pos, j);
    		}
    	}
    	sort(Q + 1, Q + 1 + q, my2);
    	for (int i = 1; i <= q; ++i) 
    	{
    		if (Q[i].ans > n - k + 1)puts("-1");
    		else Write(Q[i].ans, 1), putchar('
    ');
    	}
    }
    int main() 
    {
    	freopen("stall.in", "r", stdin);
    	freopen("stall.out", "w", stdout);
    	cin >> n >> m >> q >> k;
    	for (int i = 1; i <= m; ++i)a[i] = read();
    	solve2();
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    

    任何时候,都不要自信到连暴力分都不要。

  • 相关阅读:
    动态规划最后一击
    leetcode N-Queens I && N-Queens II
    leetcode Spiral Matrix
    leetcode Submission Details
    由网易云音乐到算法体会
    leetcode Rotate Image
    线性表之双链表
    线性表之循环单链表
    线性表之单链表
    [HDU] 1561 The more, The Better 树形DP加01分组背包
  • 原文地址:https://www.cnblogs.com/wljss/p/12173015.html
Copyright © 2020-2023  润新知