牛子题集锦

CF468C Hack it!

我们设 \(\sum_{i = 1} ^ {10^{18}} f(i) \equiv P \pmod a\),则 \(\sum_{i = 2}^{10^{18} + 1} \equiv P + 1 \pmod a\),依次类推下去。由于 \(a \le 10^{18}\),因此一定可以找到一个 \(\sum_{i = s}^{10^{18} + s} \equiv 0 \pmod a\),现在我们要求出 \(s\) 的值,那么显然 \(s = a - P\),重点就在于求 \(P\) 的值。容易知道:

\[\sum_{i = 1} ^ {10^{18}} f(i) = 9 \times 10^{17} + 2 \times \sum_{i = 1} ^ {10^{17}} f(i) \]

这样递归下去跑一下得出答案:\(81 \times 10^{18}\)。最后注意取模溢出即可。

ARC147E Examination

考虑一个选择集合 \(S\),这些集合中的数可以随意交换,并满足所有的 \(a_i < b_i\)\(i\) 都在其中。那么这个集合合法的条件即为对于所有 \(a_i\)\(b_i\) 分别从小到大排序后满足 \(\forall i \in S, a_i > b_i\)。转化成差的形式就是:

\(\forall V, \sum_{i \in S} [b_i \le V] - [a_i \le V]\ge 0\)

那么我们先将 \(a_i < b_i\)\(i\) 加入 \(S\) 中,考虑找到最小的 \(V\),使得不满足上述条件,则我们通过加入一些 \(a_i > b_i\) 的点进行调整。显然对于 \(V\) 有贡献的点 \(j\) 一定满足 \(b_j \le V < a_j\),那么我们维护一个满足 \(b_j\) 从小到大的堆,并每次将 \(b_j \le V\) 的加入到一个满足 \(a_j\) 从大到小的堆即可。

qwq
#include<bits/stdc++.h>
#define int long long
#define pir pair<int, int>
using namespace std;

const int N = 3e5 + 10;

map<int, int> tot;
priority_queue<pir, vector<pir>, greater<pir> > QB; 
priority_queue<int, vector<int>, less<int> >QA;
int n;

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n; int ans = n, now = 0;
	for(int i = 1; i <= n; i++){
		int a, b; cin >> a >> b;
		if(a < b){tot[b]++; tot[a]--; ans--;}
		else QB.push(make_pair(b, a));
	}
	for(map<int, int>::iterator it = tot.begin(); it != tot.end(); it++){
		pir ths = (*it); now += ths.second;
		while((!QB.empty()) && QB.top().first <= ths.first){
			QA.push(QB.top().second); QB.pop();
		}
		while(now < 0){
			if(QA.empty()){cout << -1; return 0;}
			if(QA.top() > ths.first){
				tot[QA.top()]--; ans--; now++;
			}
			QA.pop();
		}
	}
	cout << ans;
	
	return 0;
}

AGC027D Modulo Matrix

神秘人类智慧题。

考虑对原棋盘进行黑白染色,对于任意相同颜色的格子不会相互影响。考虑一个被 \(4\) 个黑格子夹住的白格子,设模数为 \(M\),显然一种合法的构造方就是让它等于周围四个值的 \(\operatorname{LCM} + M\)。由于有一个限制 \(a_{i, j} \le 10^{15}\),我们考虑让 \(a\) 尽量小。于是我们令 \(M = 1\)。于是我们只考虑黑色格子。注意到我们还有一个 \(a_{i, j}\) 互不相等的限制,于是我们考虑让黑色格子的数等于质数。这样黑色格子中的点互不相等,白色格子由于奇偶性的不同也不会相等。

但是这样数最大的大小约是 \(O(V^8), V = N \ln N\),显然超出限制。由于我们只关心 \(\max{a}\),而且白的很大,黑的很小,于是我们可以考虑平衡一下,让黑色格子等于两个质数的乘积,并且每条对角线的质因子一样,这样调整一下便可以通过限制。

qwq
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 5e3 + 10;

int n, a[N][N], b[N][N], c[N][N], prime[N * N], tot, cnt;
bool isprime[N * N];

void init(){
	for(int i = 2; i < N * N; i++){
		if(!isprime[i]) prime[++tot] = i;
		for(int j = 1; j <= tot && i * prime[j] < N * N; j++){
			isprime[i * prime[j]] = 1;
			if(i % prime[j] == 0) break;
		}
	}
}

int LCM(int v1, int v2, int v3, int v4){
	int val = 1;
	if(v1) val *= v1 / __gcd(val, v1);
	if(v2) val *= v2 / __gcd(val, v2);
	if(v3) val *= v3 / __gcd(val, v3);
	if(v4) val *= v4 / __gcd(val, v4); 
	return val;
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n; init();
	if(n == 2){
		cout << "4 7" << "\n" << "23 10";
		return 0;
	}
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			if(!((i + j) & 1)){
				if(b[i - 1][j - 1]) b[i][j] = b[i - 1][j - 1];
				else b[i][j] = ++cnt;
			}
		}
	}
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			if(!((i + j) & 1)){
				if(c[i - 1][j + 1]) c[i][j] = c[i - 1][j + 1];
				else c[i][j] = ++cnt;
				a[i][j] = prime[b[i][j]] * prime[c[i][j]];
			}
		}
	}
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			if(((i + j) & 1)) a[i][j] = LCM(a[i - 1][j], a[i + 1][j], a[i][j - 1], a[i][j + 1]) + 1;
		}
	}
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			cout << a[i][j] << " "; 
		}
		cout << "\n";
	}

	return 0;
}

P7207 [COCI2019-2020#3] Sob

首先观察样例并打出二进制表,可以猜测我们要将 \(a\) 中一段区间丢进 \(b\) 里进行匹配。进一步观察(啥都发现不了),可以发现它应该是一个后缀丢到前缀的形式。但是是哪个数组的前缀?这里有一个很 \(\rm nb\) 的思路:观察到题目中给的结论:“对于任意 \(n, m\) 均有解”,于是考虑将规模为 \((n, m)\) 的配对问题递归到 \((n - x, m + x)\) 规模的问题。

那么我们要找到一个 \(b\) 中的前缀并跟 \(a\) 中的后缀进行匹配,考虑如何判断 \([n - len, n - 1]\)\([m, m + len - 1]\) 是否匹配,显然有一个必要条件是 \((m + len - 1) \& (n - 1) = n - 1\)但是实际上,通过观察可以发现,这个必要条件也是充分的!这是因为对于减法影响到最高的 \(1\) 位显然都是一样的,而对于 \(0\) 位对减法是没有影响的,因此我们可以找到一个最小的 \(len\) 并划分到子问题解决。

qwq
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1e6 + 10;

int n, m;

int lowbit(int x){return x & -x;}
void solve(int len){							// has trucked
	if(len == n) return;
	int eda = n - len - 1, stb = m + len, ans = 0;
	for(int i = stb; i <= m + n - 1; i++){
		if((i & eda) == eda) {ans = i - stb + 1; break;}
	}
	for(int i = stb; i <= stb + ans - 1; i++) cout << (eda - (stb + ans - 1 - i)) << " " << i << "\n";
//	cout <<":"<< len << " " << ans << "\n";
	solve(len + ans);
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n >> m; solve(0);
	
	return 0;
}
posted @ 2024-07-23 08:19  Little_corn  阅读(6)  评论(0编辑  收藏  举报