Codeforces Round #641 div2 ABCDE & 1ABC

l比賽題目鏈接

A.Orac and Factors

題意:給你一個數每次遞歸地加上它自己的最小非1因數,問kk次之後這個數是多少?

思路:偶數一直加2,奇數先找到最小因數,加上後一定是個偶數,然後一直加2。

#include <bits/stdc++.h>
const int MAXN = 1e5 + 10;
typedef long long ll;
using namespace std;
 
 
int main() {
	int T;
	cin >> T;
	while (T--) {
		ll n, k;
		cin >> n >> k;
		if (n & 1) {
			for (int i = 3; ; i++) {
				if (n % i == 0) {
					n += i;
					break;
				}
			}
			n = n + (k - 1) * 2ll;
		}
		else {
			n = n + k * 2ll;
		}
		cout << n << endl;
	}
}

B.Orac and Models

題意:給你一個數列,讓你從中選取一個嚴格上升的子序列,且對於子序列中的任意兩個下標i,j(i<j)i,j(i<j),在原序列中的下標pi,pj(pi<pj)p_i,p_j(p_i<p_j),都有pjp_j整除pip_i,問這樣的子序列長度最長是多少?。

思路:定義dp[i]dp[i]爲原序列前ii個數的最長答案,有轉移:dp[j]=max{dp[i]+1} if(ij & a[j]>a[i])dp[j] = max\{dp[i] + 1\} \ if(i|j \ \&\ a[j]>a[i] ),複雜度O(nlog(n))O(nlog(n))。ps:比賽的時候我dfs寫的,又醜又長還會wa。。。。

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
 
int a[MAXN];
int dp[MAXN];
 
int main() {
	int T;
	cin >> T;
	while (T--) {
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
			dp[i] = 1;
		}
		int ret = 1;
		for (int i = 1; i <= n; i++) {
			for (int j = 2 * i; j <= n; j += i) {
				if (a[j] > a[i]) {
					dp[j] = max(dp[j], dp[i] + 1);
					ret = max(ret, dp[j]);
				}	
			}
		}
		cout << ret << endl;
	}
}

C.Orac and LCM

題意:求任兩個數的lcm的gcd

思路:設素數pp,假設最後的答案有pkp^k這樣一個因子,那麼pkp^k至少是原來的n1n-1個數的因子。反證法可以證明。那麼之後只要將所有的數進行因式分解,之後記錄並統計一下各個素數出現的次數即可。

另一種做法(題解):每次求出除了當前數外其他數的gcd(用前後綴)。最後再求這些gcd的lcm即爲答案,這種做法可以使得數的範圍更大~1e9,上個做法應該只能1e6左右。

#include <bits/stdc++.h>
const int MAXN = 1e5 + 10;
typedef long long ll;
using namespace std;
const int N = 1e5 + 10;
int dp[N];
const int INF = 0x3f3f3f3f;
 
 
#define pa pair<int, int>
 
const int maxn = 1e6 + 1000;
int prime[maxn] = { 0 }, phi[maxn] = { 0 }, tot = 0;
 
void euler() {
	phi[1] = 1;
	for (int i = 2; i < maxn; i++) {
		if (!phi[i]) {
			prime[tot++] = i;
			phi[i] = i - 1;
		}
		for (int j = 0; j < tot && i * prime[j] < maxn; j++) {
			if (i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			phi[i * prime[j]] = phi[i] * phi[prime[j]];
		}
	}
}
map<int, vector<int>> ma;
 
#define pa pair<int, int>
vector<pa> factor;
void init(int n) {
	factor.clear();
	for (int i = 0; prime[i] * prime[i] <= n && i < tot; i++) {
		if (n % prime[i] == 0) {
			factor.emplace_back(prime[i], 0);
			for (; n % prime[i] == 0; n /= prime[i]) factor.back().second++;
		}
	}
	if (n > 1) factor.emplace_back(n, 1);
 
	for (auto it : factor) {
		ma[it.first].push_back(it.second);
	}
}
 
int arr[MAXN];
int main() {
	euler();
	cin.tie(0);
	ios::sync_with_stdio(0);
	int n;
	while (cin >> n) {
		ma.clear();
		for (int i = 1; i <= n; i++) {
			cin >> arr[i];
			init(arr[i]);
		}
		
		ll ret = 1;
		for (auto& it : ma) {
			int tt = 0;
			if (it.second.size() == n) {
				sort(it.second.begin(), it.second.end());
				tt = it.second[1];
 
			}
			else if (int(it.second.size()) == n - 1) {
				sort(it.second.begin(), it.second.end());
				tt = it.second[0];
			}
			
			for (int i = 0; i < tt; i++) ret *= ll(it.first);
		}
 
		cout << ret << endl;
	}
}

D.Orac and Medians

題意:一個數組,每次選擇一個區間,將他們都變爲這個區間的中位數(偶數個的時候中位數取較小的那個),問最後能否把整個數組都變成kk

思路:首先判斷有沒有kk,沒kk那是肯定不行的,接着看下每連着的三個數是不是有兩個都大於等於k就行了。因爲一個小數可以直接把它隔壁的大數拖下水,而大數要兩個以上才能不斷把小數變大。比賽時候看錯題了,一下子沒思路,而且朋友叫我去打lol去了草。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int a[MAXN];
int main() {
	int T;
	cin >> T;
	while (T--) {
		int n, k;
		cin >> n >> k;
		int kf = 0;
		for (int i = 0; i < n; i++) {
			cin >> a[i];
			if (a[i] == k) kf = 1;
		}
		if (n == 1 || n == 2) {
			if (n == 2) sort(a, a + 2);
			if (a[0] == k) cout << "yes\n";
			else cout << "no\n";
		}
		else {
			int f = 0;
			for (int i = 2; i < n; i++) {
				vector<int> t = { a[i], a[i - 1],a[i - 2] };
				sort(t.begin(), t.end());
				if (t[1] >= k && t[2] >= k) {
					f = 1;
					break;
				}
			}
			if (f && kf) cout << "yes\n";
			else cout << "no\n";
		}
	}
}

E.Orac and Game of Life

題意:給你方格的初始細胞狀態(0或1),當週圍細胞有和自己狀態一樣時,會改變狀態(1->0&0->1),否則維持當前狀態不變,然後每次問題在tt時刻(x,y)(x,y)細胞是0還是1。

思路:一個細胞開始變改變狀態後,就停不下來了(因爲周圍和它一起變),所以只要bfs統計一下每個細胞是從什麼時候開始變色的就行了。ps:我覺得這比D簡單多了。

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAXN = 1e3 + 10;
const ll INF = 2e18;
char ma[MAXN][MAXN];
ll step[MAXN][MAXN];
struct nod{ int x, y; };
int dx[] = { 0,0,-1,1 };
int dy[] = { -1,1,0,0 };
int n, m, q;
void bfs() {
	queue<nod> Q;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			step[i][j] = INF;
			for (int t = 0; t < 4; t++) {
				int ni = i + dx[t];
				int nj = j + dy[t];
				if (ni >= 0 && ni < n && nj >= 0 && nj < m
					&& ma[ni][nj] == ma[i][j]) {
					Q.push({ i,j });
					step[i][j] = 0;
					break;
				}
			}
 
		}
	}
 
	while (!Q.empty()) {
		nod cur = Q.front();
		Q.pop();
 
		for (int i = 0; i < 4; i++) {
			int nx = cur.x + dx[i];
			int ny = cur.y + dy[i];
			if (nx >= 0 && nx < n && ny >= 0 && ny < m && step[nx][ny] == INF) {
				step[nx][ny] = step[cur.x][cur.y] + 1;
				Q.push({ nx, ny });
			}
		}
	}
}
int main() {
	cin >> n >> m >> q;
	for (int i = 0; i < n; i++) cin >> ma[i];
	bfs();
	while (q--) {
		int x, y;
		ll t;
		cin >> x >> y >> t;
		x--, y--;
		if (step[x][y] == INF || step[x][y] > t) cout << ma[x][y] << endl;
		else {
			t -= step[x][y];
			if (t & 1ll) cout << 1 - int(ma[x][y] - '0') << endl;
			else cout << ma[x][y] << endl;
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章