CF1567 - C~F

C Carrying Conundrum(思维)

方法一

直接dfs搜索,进位与不进,时间复杂度O(2^9)。

#include <bits/stdc++.h>

#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N) 
typedef long long ll;

using namespace std;
/*-----------------------------------------------------------------*/

ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f

const int N = 3e5 + 10;
const double eps = 1e-5;

int dig[15][2];

struct num {
	int d[15], cnt;
	num() {
		cnt = 1;
		d[0] = 0;
	};
	num(int x) {
		cnt = 0;
		do {
			d[cnt++] = x % 10;
			x /= 10;
		} while(x);
	}
	bool sub(int p) {
		while(p < cnt) {
			d[p]--;
			if(d[p] < 0) {
				d[p] += 10;
			} else break;
			p += 2;
		}
		bool flag = p < cnt;
		while(cnt > 0 && d[cnt - 1] == 0) cnt--;
		return flag;
	}
};

ll dfs(num x, int p) {
	if(p >= x.cnt) return 1;
	ll res = 0;
	res = dig[x.d[p]][0] * dfs(x, p + 1);
	if(!x.sub(p + 2)) return res;
	res += dig[x.d[p]][1] * dfs(x, p + 1);
	return res;
}

int main() {
	IOS;
	for(int i = 0; i <= 9; i++) {
		for(int j = 0; j <= 9; j++) {
			dig[(i + j) % 10][i + j >= 10]++;
		}
	}
	int t;
	cin >> t;
	while(t--) {
		int n;
		cin >> n;
		cout << dfs(num(n), 0) - 2 << endl;
	}
}

方法二

一次进两位,相当于奇数位和偶数位分别拿出来相加在合并起来。故可以拆位。时间复杂度O(nlogn)

#include <bits/stdc++.h>
 
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N) 
typedef long long ll;
 
using namespace std;
/*-----------------------------------------------------------------*/
 
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f
 
const int N = 3e5 + 10;
const double eps = 1e-5;
 
int d[N];
 
int main() {
	IOS;
	int t;
	cin >> t;
	while(t--) {
		int n;
		cin >> n;
		int cnt = 0;
		do {
			d[cnt++] = n % 10;
			n /= 10;
		} while(n);
		reverse(d, d + cnt);
		int a = 0, b = 0;
		for(int i = 0; i < cnt; i++) {
			if(i % 2) {
				a = a * 10 + d[i];
			} else {
				b = b * 10 + d[i];
			}
		}
		cout << (a + 1) * (b + 1) - 2 << endl;
	}
}

D Expression Evaluation Error(栈)

可以发现相加进位越少越优,故贪心拆成若干10^n即可。

#include <bits/stdc++.h>

#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N) 
typedef long long ll;

using namespace std;
/*-----------------------------------------------------------------*/

ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f

const int N = 3e5 + 10;
const double eps = 1e-5;

ll st[N];
int top;
vector<ll> ans;

int main() {
	IOS;
	int t;
	cin >> t;
	while(t--) {
		ans.clear();
		top = 0;
		ll s;
		int n;
		cin >> s >> n;
		ll pw = 1;
		while(s) {
			int d = s % 10;
			for(int i = 1; i <= d; i++) {
				st[top++] = pw;
			}
			s /= 10;
			pw *= 10;
		}
		reverse(st, st + top);
		while(top < n) {
			ll v = st[top - 1];
			top--;
			if(v == 1) {
				n--;
				ans.push_back(1);
			} else {
				for(int i = 1; i <= 10; i++) {
					st[top++] = v / 10;
				}
			}
		}
		while(n > 1) {
			ans.push_back(st[top - 1]);
			top--;
			n--;
		}
		ll last = 0;
		for(int i = 0; i < top; i++) last += st[i];
		ans.push_back(last);
		for(int i = 0; i < ans.size(); i++) cout << ans[i] << " \n"[i == ans.size() - 1];
	}
}

E Non-Decreasing Dilemma(线段树)

我的方法麻烦了,直接一颗线段树即可完成,直接维护递增的段和答案。

// 略

F One-Four Overload(构造)

题意

给定只由'.'和'X'构成的n x m的矩阵,要求在'.'处填入1或4,使得'X'加上相邻的'.'处的值(如果没有就为0)可以被5整除。输出构造的矩阵,不存在输出“NO”。

题解

显然,如果与'X'相邻的'.'的个数如果为奇数,必无解,所以'X'必须有偶数个相邻的'.',而且相邻的1和4的个数必须相等。

等价表示就是'X'必须与偶数个'X'相邻。如果把相邻的'X'连边,可以发现'X'要么构成一个欧拉回路,要么是一个孤立的点。'X'可以把'.'分成一个个联通块,相邻联通块之间连边。

这样得到的图必定是二部图(这个还不会证明),由于在边界处相邻的联通块颜色要求不同,所以可以直接先给联通块二染色。接着按照以下方式构造:

  1. 奇数列填1,偶数填4,从上往下染
  2. 如果当前位置对应的联通块和上面最近的联通块颜色不同,则“翻转flip”填的数(1变成4,4变成1)。

这样肯定是合法的。因为相同联通块内的,满足1和4按列交替填的规律,所以孤立的'X'位于一个联通块内,必然有上下都为1(4),左右都为4(1)合法;对于边界的'X',由于“翻转“,它上下和左右相邻的'.'将位于不同相邻的联通块,所以填的数也不一样,合法;对于'L'形相邻的'.',它们位于相同的联通块,满足交替14的规律,所以填的数也不一样,合法。

注意找联通块要八个方向找。

#include <bits/stdc++.h>

#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N) 
typedef long long ll;

using namespace std;
/*-----------------------------------------------------------------*/

ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f

const int N = 1e3 + 10;
const double eps = 1e-5;



int n, m, ind;
vector<int> np[N * N];
char arr[N][N];
int id[N][N];
int ans[N][N];
int col[N * N];

void dfs(int x, int y) {
	id[x][y] = ind;
	for(int i = x - 1; i <= x + 1; i++) {
		for(int j = y - 1; j <= y + 1; j++) {
			if(x == i && y == j || arr[i][j] == '?') continue;
			if(arr[i][j] == '.' && !id[i][j]) {
				dfs(i, j);
			}
		}
	}
}

int flip(int x) {
	return x == 1 ? 4 : 1;
}

int main() {
	IOS;
	memset(arr, '?', sizeof arr);
	cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		cin >> arr[i] + 1;
	}
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			if(arr[i][j] == '.' && !id[i][j]) {
				++ind;
				dfs(i, j);
			}
		}
	}
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			if(arr[i][j] == 'X') {
				bool flag = ((arr[i - 1][j] == '.') && (arr[i + 1][j] == '.'));
				if(flag && id[i - 1][j] != id[i + 1][j]) {
					np[id[i - 1][j]].push_back(id[i + 1][j]);
					np[id[i + 1][j]].push_back(id[i - 1][j]);
				}
			}
		}
	}
	queue<int> q;
	for(int i = 1; i <= ind; i++) {
		if(col[i]) continue;
		col[i] = 1;
		q.push(i);
		while(!q.empty()) {
			int cur = q.front();
			q.pop();
			for(int nt : np[cur]) {
				if(col[nt]) continue;
				col[nt] = (col[cur] ^ 2);
				q.push(nt);
			}
		}
	}
	
	for(int j = 1; j <= m; j++) {
		int res = (j % 2) ? 1 : 4;
		ans[1][j] = res;
		int prep = col[id[1][j]];
		for(int i = 2; i <= n; i++) {
			if(arr[i][j] == 'X') continue;
			if(prep != col[id[i][j]]) res = flip(res);
			ans[i][j] = res;
			prep = col[id[i][j]];
		}
	}

	bool ok = true;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			if(arr[i][j] == 'X') {
				int num = 0;
				if(arr[i - 1][j] == '.') {ans[i][j] += ans[i - 1][j]; num++;}
                if(arr[i + 1][j] == '.') {ans[i][j] += ans[i + 1][j]; num++;}
                if(arr[i][j - 1] == '.') {ans[i][j] += ans[i][j - 1]; num++;}
                if(arr[i][j + 1] == '.') {ans[i][j] += ans[i][j + 1]; num++;}
				if(num % 2) ok = false;
			}
		}
	}
	if(ok) {
		cout << "YES" << endl;
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= m; j++) {
				cout << ans[i][j] << " \n"[j == m];
			}
		}
	} else {
		cout << "NO" << endl;
	}
}
posted @ 2021-09-08 19:49  limil  阅读(62)  评论(0编辑  收藏  举报