• AtCoder Beginner Contest 132


    [TOC]

    Contest Info


    [Practice Link](https://atcoder.jp/contests/abc132/tasks)
    Solved A B C D E F
    6/6 O O O O Ø O
    • O 在比赛中通过
    • Ø 赛后通过
    • ! 尝试了但是失败了
    • - 没有尝试

    Solutions


    A. Fifty-Fifty

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
    	string s; cin >> s;
    	sort(s.begin(), s.end());
    	s.erase(unique(s.begin(), s.end()), s.end());
    	cout << (((int)s.size() == 2) ? "Yes" : "No") << "
    ";
    	return 0;
    }
    

    B. Ordinary Number

    #include <bits/stdc++.h>
    using namespace std;
    
    #define N 50
    int n, a[N];
    
    int main() {
    	while (scanf("%d", &n) != EOF) {
    		for (int i = 1; i <= n; ++i) {
    			scanf("%d", a + i);
    		}
    		int res = 0;
    		for (int i = 2; i < n; ++i) {
    			int f = a[i] < a[i - 1];
    			int g = a[i] < a[i + 1];
    			if (f ^ g) {
    				++res;
    			}
    		}
    		printf("%d
    ", res);
    	}
    	return 0;
    }
    

    C. Divide the Problems

    #include <bits/stdc++.h>
    using namespace std;
    
    #define N 100010
    int n, a[N];
    
    int main() {
    	while (scanf("%d", &n) != EOF) {
    		for (int i = 1; i <= n; ++i) {
    			scanf("%d", a + i);
    		}
    		sort(a + 1, a + 1 + n);
    		int mid = n / 2;
    		if (a[mid] == a[mid + 1]) {
    			puts("0");
    		} else {
    			printf("%d
    ", a[mid + 1] - a[mid]);
    		}
    	}
    	return 0;
    }
    

    D. Blue and Red Balls

    题意: 有$K$个蓝球,$N - K$个红球,询问将蓝球分成$i(1 leq i leq k)$堆,中间用红球隔开的方案数分别是多少?

    思路: 考虑先将$k$个蓝球分成$i$堆,然后每堆后面跟着一个红球,然后就有$i + 1$个空隙,剩下的红球相当于要放入$i + 1$个空箱中,允许空箱的经典问题。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define N 2010
    const int p = 1e9 + 7;
    int n, k;
    ll fac[N], inv[N];
    ll qmod(ll base, ll n) {
    	ll res = 1;
    	while (n) {
    		if (n & 1) {
    			res = res * base % p;
    		}
    		base = base * base % p;
    		n >>= 1;
    	}
    	return res;
    }
    
    ll C(int n, int m) {
    	if (n < m) return 0;
    	return fac[n] * inv[m] % p * inv[n - m] % p;
    }
    
    ll f(int n, int i, int k) {
    	ll remind = n - k;
    	if (n - k < i - 1) {
    		return 0;
    	}
    	remind -= i - 1;
    	return C(k - 1, i - 1) * C(i + remind, i) % p; 
    }
    
    int main() {
    	fac[0] = 1;
    	for (int i = 1; i <= 2000; ++i) {
    		fac[i] = fac[i - 1] * i % p;
    	}
    	inv[2000] = qmod(fac[2000], p - 2);
    	for (int i = 2000; i >= 0; --i) {
    		inv[i - 1] = inv[i] * i % p;
    	}
    	while (scanf("%d%d", &n, &k) != EOF) {
    		for (int i = 1; i <= k; ++i) {
    			printf("%lld
    ", f(n, i, k));
    		}
    	}
    	return 0;
    }
    

    E. Hopscotch Addict

    题意: 求$S$到$T$的最短路,并且要满足其长度是$3$的倍数。

    思路: $dis[i][j]$表示到第$i$个点,长度模$3$的值为$j$的最短路是多少,然后跑Dijkstra即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define INF 0x3f3f3f3f
    #define N 100010
    int n, m, s, t;
    vector <vector<int>> G;
    struct node {
    	int u, w;
    	node() {}
    	node (int u, int w) : u(u), w(w) {}
    	bool operator < (const node &other) const {
    		return w > other.w;
    	}
    };
    
    int dis[N][3], used[N][3];
    void BFS() {
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 0; j < 3; ++j) {
    			dis[i][j] = INF;
    			used[i][j] = 0;		
    		}
    	}
    	dis[s][0] = 0;	
    	priority_queue <node> pq;
    	pq.push(node(s, 0)); 
    	while (!pq.empty()) {
    		int u = pq.top().u, w = pq.top().w; pq.pop(); 
    		if (used[u][w % 3]) continue;
    		used[u][w % 3] = 1;
    		for (auto v : G[u]) {
    			if (dis[v][(w + 1) % 3] > w + 1) {
    				dis[v][(w + 1) % 3] = w + 1;  
    				pq.push(node(v, w + 1));  
    			}
    		}
    	}
    }
    
    int main() {
    	while (scanf("%d%d", &n, &m) != EOF) {
    		G.clear(); G.resize(n + 1);
    		for (int i = 1, u, v; i <= m; ++i) {
    			scanf("%d%d", &u, &v);
    			G[u].push_back(v);
    		}
    		scanf("%d%d", &s, &t);
    		BFS();
    		if (dis[t][0] == INF) puts("-1");
    		else {
    			printf("%d
    ", dis[t][0] / 3);
    		}
    	}
    	return 0;
    }
    

    F. Small Products

    题意: 构造一个长度为$k$的,并且相邻两数之积不超过$N$的序列的方案数是多少?

    思路: $f[i][j]$表示到第$i$位,当前位为$j$的方案数是多少。 暴力$DP$显然不行。 但是我们考虑我们每次对于$j$转移的都是$sumlimits_^{N / j} f[i - 1][j]$,考虑到$N / j$的取值只有$2sqrt$种,所以只需要存$k cdot 2sqrt$种状态。转移即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define N 110
    #define M 100010
    #define pii pair <int, int>
    #define fi first
    #define se second
    const ll p = 1e9 + 7;
    int n, k;
    ll f[N][M];
    pii g[M]; 
    map <int, int> mp;
    
    int main() {
    	while (scanf("%d%d", &k, &n) != EOF) {
    		memset(f, 0, sizeof f);
    		mp.clear();
    		int m = 0;
    		for (int i = 1, j; i <= k; i = j + 1) {
    			j = k / (k / i);
    			g[++m] = pii(j, j - i + 1);
    			mp[j] = m;
    		}
    		for (int i = 1; i <= m; ++i) {
    			f[1][i] = (f[1][i - 1] + g[i].se) % p; 
    		}
    		for (int i = 2; i <= n; ++i) {
    			for (int j = 1; j <= m; ++j) {
    				f[i][j] = (f[i][j - 1] + 1ll * g[j].se * f[i - 1][mp[k / g[j].fi]] % p) % p;
    			}
    		}
    		printf("%lld
    ", f[n][m]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    X lvm管理:扩展lv、删除pv、lv,删除物理卷PV
    X 如何在Linux中缩小LVM大小(逻辑卷调整)如何在Linux中缩小LVM大小(逻辑卷调整)
    元素和为目标值的子矩阵数量
    完美矩形问题
    桶排序算法
    组合数组合
    求两个有序数组的第k大的数(默认两有序数组都为从小到大)
    二叉树的遍历
    卡特兰数
    二叉排序树
  • 原文地址:https://www.cnblogs.com/Dup4/p/11148059.html
Copyright © 2020-2023  润新知