• Codeforces Round #536 (Div. 2)


    Codeforces Round #536 (Div. 2)

    A

    题目大意

    给你一个(n imes n(nleqslant500))的矩阵,只包含.X,问最多可以找到多少个(cross),一个(cross)为如下图形:

    X_X
    _X_
    X_X
    

    _表示可以为任意字符。不同的(cross)之间可以重叠

    题解

    可以枚举中间X,判断是否合法

    卡点

    C++ Code:

    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    #define maxn 510
    
    int Tim, n, m, ans;
    char s[maxn][maxn];
    int main() {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; ++i) {
    		scanf("%s", s[i] + 1);
    	}
    	for (int i = 2; i < n; ++i) {
    		for (int j = 2; j < n; ++j) if (s[i][j] == 'X') {
    			if (s[i - 1][j - 1] == 'X' && s[i + 1][j - 1] == 'X'
    					&& s[i - 1][j + 1] == 'X' && s[i + 1][j + 1] == 'X') ++ans;
    		}
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
    

    B

    题目大意

    (n(nleqslant10^5))道菜,第(i)道菜有(a_i)份,每个价值都为(c_i)。有(m(mleqslant10^5))个顾客,第(i)个顾客要(d_i)份第(t_i)种菜(只有第(i)个顾客走后第(i+1)个顾客才会来)。餐厅按如下规则给菜(一份菜一份菜给):

    1. 若当前有第(t_i)种菜,就给该顾客一份
    2. 若没有第(t_i)种菜,就给该顾客最便宜的菜,若有多个最便宜的菜,给编号最小的
    3. 若没有菜,顾客会愤怒的离开

    若该顾客没有愤怒的离开,输出餐厅给的菜的价值总和,若离开了,输出(0)(注意,已经给这个顾客的菜依然给了这个顾客,也就是说无法回收菜)

    题解

    原来的题目中似乎没有注意部分,导致我以为是线段树上二分,然后不想写,先写了(C)(D),然后出题人发公告。于是变成了真正的(B)题难度。

    只需要记录一下价值最小的没有被用完的菜就行了,直接模拟即可,发现一道菜只会被用完一次,所以复杂度是(O(n+m))

    卡点

    C++ Code:

    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    #define maxn 100010
    
    int Tim, n, m, lst;
    long long a[maxn], c[maxn];
    int ret[maxn], rnk[maxn];
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    	std::cin >> n >> m;
    	for (int i = 1; i <= n; ++i) {
    		std::cin >> a[i];
    	}
    	for (int i = 1; i <= n; ++i) {
    		std::cin >> c[i];
    		rnk[i] = i;
    	}
    	std::sort(rnk + 1, rnk + n + 1, [] (int a, int b) { return c[a] < c[b]; });
    	for (int i = 1; i <= n; ++i) ret[rnk[i]] = i;
    	lst = 1;
    	while (m --> 0) {
    		long long t, d, ans = 0;
    		std::cin >> t >> d;
    		if (a[t] >= d) {
    			a[t] -= d;
    			std::cout << d * c[t] << '
    ';
    			continue;
    		}
    		ans = a[t] * c[t];
    		d -= a[t];
    		a[t] = 0;
    		for (int i; lst <= n; ++lst) {
    			i = rnk[lst];
    			if (a[i] >= d) {
    				ans += d * c[i];
    				a[i] -= d;
    				d = 0;
    				std::cout << ans << '
    ';
    				break;
    			}
    			ans += a[i] * c[i];
    			d -= a[i];
    			a[i] = 0;
    		}
    		if (d) std::cout << "0
    ";
    	}
    	return 0;
    }
    
    

    C

    题目大意

    (n(nleqslant3 imes10^5))个数,保证(n)为偶数,要把它们分成若干组,每组至少两个数。假设分成(m)组,第(i)组的和为(s_i),要求最小化(sumlimits_{i=1}^ms_i^2)

    题解

    发现一定是每组两个数,因为把两个总和分别为(a,b)的组合起来的时候,代价从(a^2+b^2)变为了(a^2+2ab+b^2)肯定不优秀。继续发现要让(max{s_i})最小,于是排一个序,每次取最小和最大的放为一组即可。

    卡点

    C++ Code:

    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    #define maxn 300010
    
    int Tim, n, m;
    int s[maxn];
    long long ans;
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0);
    	std::cin >> n;
    	for (int i = 0; i < n; ++i) std::cin >> s[i];
    	std::sort(s, s + n);
    	const int nn = n >> 1;
    	for (int i = 0, x; i < nn; ++i) {
    		x = s[i] + s[n - i - 1];
    		ans += x * x;
    	}
    	std::cout << ans << std::endl;
    	return 0;
    }
    
    

    D

    题目大意

    给你一张(n(nleqslant10^5))个点(m(mleqslant10^5))条边的无向图,现在在点(1),每次到一个没有经过过的点就把那个点记录下来,直到经过所有(n)个点,问最后记录下的序列最小的字典序是什么,可以重复经过点和边。

    题解

    这可比(NOIP2018D2T1)简单多了,只需要求一个一个类似最小生成树的东西就行了。用一个小根堆记录当前经过过的点可以到达的没有经过过的点,每次取出堆顶,把与它相连的点加入堆即可。

    卡点

    C++ Code:

    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    #define maxn 100010
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt;
    } e[maxn << 1];
    inline void addedge(int a, int b) {
    	e[++cnt] = (Edge) { b, head[a] }; head[a] = cnt;
    	e[++cnt] = (Edge) { a, head[b] }; head[b] = cnt;
    }
    
    int Tim, n, m;
    std::priority_queue<int, std::vector<int>, std::greater<int> > q;
    bool inq[maxn];
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    	std::cin >> n >> m;
    	for (int i = 0, a, b; i < m; ++i) {
    		std::cin >> a >> b;
    		addedge(a, b);
    	}
    	q.push(1);
    	inq[1] = true;
    	for (int Tim = 1; Tim < n; ++Tim) {
    		int u = q.top(); q.pop();
    		std::cout << u << ' ';
    		for (int i = head[u]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if (!inq[v]) {
    				q.push(v);
    				inq[v] = true;
    			}
    		}
    	}
    	std::cout << q.top() << std::endl;
    	return 0;
    }
    
    

    E

    题目大意

    (n(nleqslant10^5))个时间点,分别为(1sim n),有(k(kleqslant10^5))个红包,第(i)个红包可以在([s_i,t_i])内领取,有钱(w_i),领了这个红包,直到(d_i)时间点之后(不包含(d_i))才可以领取下一个红包。

    (Bob)按如下规则领红包:

    1. 领当前可以领的最大的红包
    2. 若有多个,领(d)最大的红包
    3. 若还有多个,随机领一个

    (Alice)希望(Bob)领的最少,她可以在最多(m(mleqslant200))个时间点打扰(Bob),使得他不能领红包,问(Bob)最少领到多少钱

    题解

    (比赛时做(F)题,就没有做(E),而且(F)没在比赛内写出来。。。。)

    发现每个时间点(Bob)领的红包是一定的,可以预处理出来,用(set,map)什么的,注意有重复元素,设第(i)个时间点领的红包为(s_i)

    (f_{i,j})表示打断了(i)次,现在在第(j)个时间点(Bob)领的最少钱数,转移为(f_{i.j} o f_{i+1,j+1})(f_{i,j}+w_{s_j} o f_{i,d_{s_j}})

    卡点

    C++ Code:

    #include <algorithm>
    #include <cstdio>
    #include <iostream>
    #include <map>
    #include <vector>
    #define maxn 100010
    typedef std::pair<int, int> PII;
    const long long inf = 0x3f3f3f3f3f3f3f3f;
    inline void chkmin(long long &a, long long b) { if (a > b) a = b; }
    
    int n, m, k, now = 1, nxt;
    long long f[2][maxn], ans = inf;
    std::vector<PII> Add[maxn], Del[maxn];
    PII Max[maxn];
    std::map<PII, int> mp;
    
    
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    	std::cin >> n >> m >> k;
    	for (int i = 0, s, t, d, w; i < k; ++i) {
    		std::cin >> s >> t >> d >> w;
    		Add[s].push_back(std::make_pair(w, d));
    		Del[t + 1].push_back(std::make_pair(w, d));
    	}
    	for (int i = 1; i <= n; ++i) {
    		for (PII V : Add[i]) {
    			if (mp.count(V)) ++mp[V];
    			else mp[V] = 1;
    		}
    		for (PII V : Del[i]) {
    			if (!--mp[V]) mp.erase(V);
    		}
    		if (mp.size()) Max[i] = (*mp.rbegin()).first;
    		else Max[i] = std::make_pair(0, i);
    	}
    
    	const int SZ = sizeof f[now];
    	__builtin_memset(f[nxt], 0x3f, SZ);
    	f[nxt][1] = 0;
    	for (int i = 0; i <= m; ++i) {
    		std::swap(now, nxt);
    		__builtin_memset(f[nxt], 0x3f, SZ);
    		f[nxt][1] = 0;
    		for (int j = 1; j <= n; ++j) {
    			chkmin(f[nxt][j + 1], f[now][j]);
    			chkmin(f[now][Max[j].second + 1], f[now][j] + Max[j].first);
    		}
    		chkmin(ans, f[now][n + 1]);
    	}
    	std::cout << ans << std::endl;
    	return 0;
    }
    
    

    F

    题目大意

    有一串(n(nleqslant10^9))个数的数列,给你(b_1sim b_k(kleqslant100))。当(i>k)时:

    [f_i=(prodlimits_{i=1}^kf_{i-j}^{b_i})mod{998244353} ]

    已知(f_1=f_2=cdots=f_{k-1}=1,f_n=m),问最小的正整数(f_k)可能是多少

    题解

    写一下式子,发现可以用矩阵快速幂求出(f_n=f_k^xmod{998244353})中的(x)(幸好这道题不需要线性齐次递推,不然玩完),复杂度(O(k^3log_2n))

    接下来就是求(f_k^xequiv mpmod{998244353})

    [xln(f_k)equivln(m)pmod{varphi(998244353)}\ ln(f_k)equivln(m)x^{-1}pmod{998244352}\ f_kequivexp(ln(m)x^{-1})pmod{998244353}\ ]

    但是(x)(pmod{998244352})下可能没有逆元,怎么办呢?可以用(exgcd)求出(dfrac{gcd(x,998244352)}x),然后把(ln(m))除掉(gcd(x,998244352)),若有余数则无解。

    卡点

    比赛结束后(5min)发现可以除掉(gcd)来做,然后自闭

    C++ Code:

    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    const int mod = 998244353, __mod = mod - 1;
    #define maxn 105
    
    int Tim, n, m, k;
    int b[maxn];
    struct Matrix {
    	int s[maxn][maxn];
    	inline Matrix operator * (const Matrix &rhs) const {
    		Matrix res;
    		for (int i = 0; i < k; ++i) {
    			for (int j = 0; j < k; ++j) {
    				long long t = 0;
    				for (int l = 0; l < k; ++l) (t += static_cast<long long> (s[i][l]) * rhs.s[l][j]) %= __mod;
    				res.s[i][j] = t;
    			}
    		}
    		return res;
    	}
    } base, res;
    
    namespace Math {
    	std::map<int, int> mp;
    	bool init = false;
    	long long BSGS(long long y, long long z) {
    		y %= mod, z %= mod;
    		if (!y) return -1;
    		long long tmp = 1, t = sqrt(mod - 1) + 1;
    		if (!init) {
    			mp.clear();
    			for (int i = 0; i <= t; i++) {
    				mp[tmp * z % mod] = i;
    				if (i != t) tmp = tmp * y % mod;
    			}
    			init = true;
    		}
    		long long tmp6 = tmp;
    		for (int i = 1; i <= t; i++) {
    			if (mp.count(tmp6)) return i * t - mp[tmp6];
    			tmp6 = tmp6 * tmp % mod;
    		}
    		return -1;
    	}
    
    	inline int pw(int base, int p) {
    		static int res;
    		for (res = 1; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod;
    		return res;
    	}
    
    	long long exgcd(long long a, long long b, long long &x, long long &y) {
    		if (!b) {
    			x = 1, y = 0;
    			return a;
    		}
    		long long t = exgcd(b, a % b, y, x);
    		y -= a / b * x;
    		return t;
    	}
    	long long retgcd;
    	long long inv(long long a) {
    		long long x, y;
    		retgcd = exgcd(a, __mod, x, y);
    		return (x % __mod + __mod) % __mod;
    	}
    }
    
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    	std::cin >> k;
    	for (int i = 0; i < k; ++i) std::cin >> base.s[i][0];
    	for (int i = 1; i < k; ++i) base.s[i - 1][i] = 1;
    	res.s[0][0] = 1;
    	std::cin >> n >> m;
    	for (n -= k; n; n >>= 1, base = base * base) if (n & 1) res = res * base;
    	const long long y = res.s[0][0];
    	long long lnz = Math::BSGS(3, m);
    	long long t = Math::inv(y);
    	if (lnz % Math::retgcd) {
    		puts("-1");
    		return 0;
    	}
    	lnz = lnz / Math::retgcd * t % __mod;
    	std::cout << Math::pw(3, lnz) << '
    ';
    	return 0;
    }
    
    
  • 相关阅读:
    mysql启动错误
    maven环境变量配置
    记一次服务器Tomcat优化经历
    自动定时备份删除脚本
    Tomcat网页加载速度过慢的解决方法
    tomcat运行war包报错,找不到context-root文件
    maven下配置pom.xml
    [LeetCode]题解(python):116-Populating Next Right Pointers in Each Node
    [LeetCode]题解(python):115-Distinct Subsequences
    [LeetCode]题解(python):114-Flatten Binary Tree to Linked List
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10345347.html
Copyright © 2020-2023  润新知