zoukankan      html  css  js  c++  java
  • CF1567

    C Carrying Conundrum(思维)

    方法一

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

    #include <bits/stdc++.h>
    
    #define endl '
    '
    #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 '
    '
    #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 '
    '
    #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] << " 
    "[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 '
    '
    #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] << " 
    "[j == m];
    			}
    		}
    	} else {
    		cout << "NO" << endl;
    	}
    }
    
  • 相关阅读:
    数数小木块
    Triangular Sums
    Financial Management
    阶乘因式分解(一)
    另一种阶乘问题
    韩信点兵
    Fibonacci数
    A+B Problem
    16进制的简单运算
    浅谈数据库之事务
  • 原文地址:https://www.cnblogs.com/limil/p/15244339.html
Copyright © 2011-2022 走看看