Codeforces 950 010子序列拆分 数列跳棋
A
B
a,b两个序列分成K段 每一段的值相等
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-10; const double EPS = 1.0e-4; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int maxn = 100005; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll mod = 3e7; ll num[maxn]; ll num2[maxn]; //priority_queue<int, vector<int>, less<int>> que; int main() { int n, m; ll now; cin >> n >> m; for (int i = 1; i <= n; i++) { scanf("%lld", num+i); //pre[i] = pre[i - 1] + now; } for (int i = 1; i <= m; i++) { scanf("%lld", num2+i); //pre2[i] = pre2[i - 1] + now; } int cur = 1; int cur2 = 1; ll sum1 = num[1]; ll sum2 = num2[1]; int anser = 0; while (cur != n + 1) { if (sum1 == sum2) { anser++; sum1+=num[++cur]; sum2+=num2[++cur2]; continue; } if(sum1<sum2) { sum1+=num[++cur]; } else { sum2+=num2[++cur2]; } } cout<<anser<<endl; }
C
问子序列可否全部分成0或者010 01010这种01相间的序列
用Vector和一个int指针维护 int之前的vector表示以0结尾的 之后的表示以1结尾的
如果指针在插入一个1前是在0或者全部插入完还有以1结尾的就return false
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-10; const double EPS = 1.0e-4; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int maxn = 100005; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll mod = 3e7; vector<int> ans[200005]; int anser = 0; int cnt = 0; //priority_queue<int, vector<int>, less<int>> que; int main() { string a; cin >> a; int len = a.size(); for (int i = 0; i < len; i++) { if (a[i] == '0') { ans[++cnt].pb(i + 1); } else { if (cnt <= 0) //!!!!!!!!!!!! { cout << -1 << endl; return 0; } ans[cnt--].pb(i + 1); } anser = max(anser, cnt); } if (cnt != anser) { cout << -1 << endl; return 0; } cout << anser << endl; for (int i = 1; i <= anser; i++) { int lenth = ans[i].size(); cout << lenth << " "; for (int j = 0; j < lenth; j++) { cout << ans[i][j] << " "; } cout << endl; } }
D
思维题 可以找规律做 也可以推公式做
很容易想到原本序列前N/2个数的位置是不会变的 因为这些数一旦跳了 最后序列的长度就会小于N 这些数在最后的位置下标为奇数位
然后其他跳的数 假设他跳之后的位置为P 则现在在他左边的P/2个数是原数组原来就在他左边的
右边有N-P/2个数(包括他自己)是连续的 也就是说他之前的位置往前进了N-P/2个块
所以公式就是P=P/2+N 一直循环直到P为奇数为止 这就是最终序列的数对应原来序列的位置
最后答案就是P/2+1
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-10; const double EPS = 1.0e-4; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation priority_queue<int, vector<int>, less<int>> que; ll mod = 3e7; const int MAXN = 505; int main() { ll n; ll q; cin >> n >> q; while(q--) { ll now; cin >> now; while(!(now%2)) { now=now/2+n; } cout<<now/2+1<<endl; } }