心得体会:写这一场,让我发现了一个事情,py跑1e6的数据基本上就炸了,还是求稳C++好一些。但是还是想练一下py然后选择了py写。
题目大意:给定一个n个数字的数组,要求你找出一种选取方法,使得选出来的数字里,没有超过a[1]一半的数字,并且要求选出来的数字总和大于等于n个数字之和的一半。
分析:简单的模拟,模出来看看合不合理就行了。
代码:
k = eval(input()) a = input().split() for i in range(k): a[i] = int(a[i]) tot = 0 for i in range(k): tot += a[i] if k == 2: if a[0] > a[1]: print('1 1') else: print(0) else: can = a[0] party = [] party.append(1) for i in range(k): if a[0] >= a[i] * 2 and len(party) < k -1: can += a[i] party.append(i+1) if can * 2 > tot: print(len(party)) for i in party: print(i, end = " ") else: print(0)
题目大意:故意把w写成紧挨的两个vv,问你有多少个wow子序列。
分析:O(n)跑出每个字母o两端的紧挨的vv的个数,然后左边乘以右边的相加即可。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+7; typedef long long ll; char s[maxn]; int l[maxn],r[maxn]; int main(){ cin>>s; int n=strlen(s); ll tot = 0; l[0] = 0; for(int i=1;i<n;i++){ if(s[i-1]=='v'&&s[i]=='v') tot ++; l[i] = tot; } r[n-1] = 0; tot = 0; for(int i=n-1;i>=1;i--) { if (s[i] == 'v' && s[i - 1] == 'v') tot++; r[i - 1] = tot; } ll ans = 0; for(int i=0;i<n;i++){ if(s[i]=='o') ans += (ll)l[i] * r[i]; } cout<<ans<<endl; return 0; }
题目大意:给定N x M大的区域,让你用1 X 1的方块去填,每个方块是由一个黑色三角形和一个白色三角形拼接起来的,并且要求相邻的两个方块的相邻线处的颜色不能相同,问你有多少种合适的放置方式,注意mod = 998244353。
分析:猜了个结论,1<<(n + m),还真的猜对了,直接秒过。
代码:
mod = 998244353 def quick_pow(a, b): res = 1 while b > 0: if b & 1: res = res * a % mod a = a * a % mod b >>= 1 return res n, m = input().split() n = int(n) m = int(m) print(quick_pow(2, n + m))
题目大意:给定顶点的个数,让你构造出一张无向图,使得每个顶点的度数为素数,并且图的边数也为素数。
分析:先依次把每个点连上,使得每个顶点的度数都为2即可。然后连圈内的边,一直到边的条数为素数即可。
代码:
prime = [] maxn = 100000 G = [] def init(): for i in range(1007): G.append([]) for j in range(1007): G[i].append(0) def sieve(): for i in range(maxn): prime.append(1) prime[0] = prime[1] = 0 for i in range(maxn): if prime[i]: j = 2 * i while j < maxn: prime[j] = 0 j += i init() sieve() n = eval(input()) tot = 0 for i in range(1, n): G[i][i+1] = 1 tot += 1 G[1][n] = 1 tot += 1 j = n - 1 i = 1 while j > i: if prime[tot]: break G[i][j] = 1 tot += 1 i += 1 j -= 1 print(tot) for i in range(1, n + 1): for j in range(1, n + 1): if G[i][j]: print(str(i)+' '+str(j))
题目大意:给定一个字符串,让你找出一个长度不小于原字符串一半的回文子序列。
分析:直接模拟就行了,只用比较三个位置,s[l]和s[r],s[l - 1]和s[r],s[l]和s[r - 1]。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+7; char s[maxn]; bool vis[maxn]; int main() { cin >> s; int n = strlen(s); int l = 0, r = n - 1, cnt = 0; while (l <= r) { if (s[l] == s[r]) { vis[l] = vis[r] = true; if (l == r) cnt += 1; else cnt += 2; l += 1; r -= 1; } else if (s[l + 1] == s[r]) { vis[l + 1] = vis[r] = true; if (l + 1 == r) cnt += 1; else cnt += 2; l += 2; r -= 1; } else if (s[l] == s[r - 1]) { vis[l] = vis[r - 1] = true; if (l == r - 1) cnt += 1; else cnt += 2; l += 1; r -= 2; } else { r -= 1; l += 1; } } for (int i = 0; i < n; i++) if (vis[i]) printf("%c", s[i]); return 0; }