标签:gre back 后缀 有序 数值 序列 code print else
https://codeforces.com/contest/1474
A√
题意:
现有两个长度为n的0,1字符串a,b(其中仅包含0,1),对两个字符串相加得到字符串c(按数值不进位相加);
例如:
a=“011011”;
b=“101101”;
则c=“112112”;
之后将c中的连续重复数字替换为一位得到字符串d,对于上述c它的对应字符串d=“1212”;
输出:题目给出一个字符串b;求一个字符串a使得a+b对应的字符串d最大;
#include <bits/stdc++.h> using namespace std; int main() { int t; scanf("%d",&t); while(t--) { string s; int num; scanf("%d",&num); int a[num]={0}; int flag[num]={0}; cin>>s; for(int i=0;i<num;i++) { if(i==0) { a[i]=1; flag[i]=1; } else{ if(((s[i]==s[i-1])&&!flag[i-1])||((s[i-1]==‘0‘)&&(s[i]==‘1‘))||((s[i-1]==‘1‘)&&(s[i]==‘0‘)&&(flag[i-1]==1))) { a[i]=1; flag[i]=1; } else{ a[i]=0; } } } for(int i=0;i<num;i++) printf("%d",a[i]); printf("\n"); } return 0; }
B√
题意:
题意比较简单
给了一个整数d让我们找出最小的正整数a,使得a至少有4个因子且a的任意两个因数之差至少为d。
解析:
1:对于一些素数p和q,整数有4个约数,如果它的形式是p×q或p3。在第一种情况下,它有1,p, q, pq。
在第二种情况下,它有因子1 p p2 p3。
2:根据贪心,本题不是找到至少有4个约数的整数,而是找到恰好有4个约数的整数(任意两个因数相差大于等于d)。
3:若p为a最小的质因数,要使得任意两个因数只差至少为d则p≥d+1。
则解法为:
四个因数,第一个为1,第四个为a,则中间两个就为第一个比1大于等于d的质数和第一个比第二个因数大于等于的质数,将它们相乘即可得到 a
即:1,d+m,d+m+n,(d+m)(d+d+m)(m为找不到恰好相差d的时候找到的第一个大于d的质数-d,n同理)
^^^
lower_bound( )和upper_bound( )都是利用二分查找的方法,左闭右开的有序区间里进行二分查找的。
两个函数在algorithm头文件下;
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字;
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字;
找到返回该数字的地址,不存在则返回end
#include <bits/stdc++.h> typedef long long ll; using namespace std; const int N=200005; bool vis[N]; ll primer[N];//存素数 int cnt=0; void find_primer(){//欧拉筛 for(ll i=2;i<=N;i++){ if(!vis[i])primer[cnt++]=i; for(ll j=0;j<cnt&&primer[j]*i<=N;j++){ vis[i*primer[j]]=1; if(i%primer[j]==0)break; } } } int main() { string s,c; int T; cin>>T; int n; find_primer(); // for(int i=0;i<=10000;i++){ // cout<<primer[i]<<endl; // } while(T--){ scanf("%d",&n);//差值n ll ans=0; ll a=upper_bound(primer,primer+cnt,n)-primer;//二分查找找到第一个差值为n的质数; // cout<<"**"<<a<<endl; a=primer[a]; // cout<<"****"<<a<<endl; ll b=lower_bound(primer,primer+cnt,a+n)-primer;//二分查找找到第二个差值为n的质数 b=primer[b]; ans=a*b;//相乘求得ans的值 cout<<ans<<endl; } return 0; }
C
题目:
给出2n个数,初始可以指定任意的数作为基数,然后将数组中和为基数的两个数删除,较大的数作为新的基数,问如此往复是否可以删除所有的数,并输出每轮的基数
解析:
注意:
#include<bits/stdc++.h> using namespace std; /*===========================================*/ const int maxn = 2005; const int M = 1e6 + 5; int dat[maxn]; multiset<int, greater<int>> s; vector<pair<int, int>> ans; int n, T; int main() { scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 1; i <= 2 * n; ++i) scanf("%d", &dat[i]); sort(dat + 1, dat + 2 * n + 1); for (int i = 1; i < 2 * n; ++i) { ans.clear(); s.clear(); int last = dat[2 * n]; ans.push_back(pair<int, int>(dat[2 * n], dat[i])); for (int j = 1; j < 2 * n; ++j) if (j != i) s.insert(dat[j]); while (!s.empty()) { multiset<int, greater<int>>::iterator t; int tmp = *s.begin(); s.erase(s.begin()); if ((t = s.find(last - tmp)) != s.end()) { ans.push_back(pair<int, int>(tmp, *t)); last = tmp; s.erase(t); } else break; } if (ans.size() == n) break; } if (ans.size() == n) { printf("YES\n%d\n", ans[0].first + ans[0].second); for (auto& i : ans) printf("%d %d\n", i.first, i.second); } else printf("NO\n"); } }
D
给n个数,每次选相邻的两个数都减一,当第i堆减到0时,第i?1和第i+1堆也不算是相邻,问在删除前允许交换任意相邻数一次的前提下能不能把所有数归零。
易知消除顺序不重要。
①如果不交换就能达成。 a1<=a2<=a3……<=ai an<=an-1<=an-2<=…… 设li 是第i个在消除后剩下的值 li = ai - li-1
维护前缀后缀和
②必须交换的。 以ai为基础 1~i-1前缀 i+2~n后缀 再判断 li-1 ai ai+1 si+2 是否满足
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn = 1e6 + 5; const int mod = 1e9 + 7; ll a[maxn] , p[maxn] , s[maxn]; int main() { ios::sync_with_stdio(false); int t; cin >> t; while (t--){ int n ; cin >> n; for (int i = 1 ; i <= n ; i++) cin >> a[i]; p[0] = 0; for (int i = 1 ; i <= n ; i++) { if (p[i - 1] == -1) p[i] = -1; else p[i] = max( -1ll , a[i] - p[i - 1] ); } s[n + 1] = 0; for (int i = n ; i >= 1 ; i--) { if (s[i + 1] == -1) s[i] = -1; else s[i] = max( -1ll , a[i] - s[i + 1] ); } bool ok = true; for (int i = 1 ; i < n ; i++) if (p[i] == -1) ok = false; if (p[n]) ok = false; if (ok) { cout << "YES" << endl; continue; } for (int i = 1 ; i < n && !ok; i++) { // if (p[i - 1] == -1 || s[i + 2] == -1) continue; ll tmp[4] = {p[i - 1] , a[i + 1] , a[i] , s[i + 2]}; for (int j = 1 ; j <= 3 ; j++) { if (tmp[j - 1] == -1) tmp[j] = -1; else tmp[j] = max (-1ll , tmp[j] - tmp[j - 1]); } ok |= (tmp[1] >= 0 && tmp[2] >= 0 && tmp[3] == 0); } cout << (ok ? "YES" : "NO") << endl; } return 0; }
E
题目:
给出一个长度n,给出操作(i,j),p[j]=i?swap(i,j),但要付出(i?j)2的代价,现需要求出对应的长度为n的排列可能拥有的最大代价、排列本身以及中间的操作过程
解析:
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<b;++i) #define rep1(i,a,b) for(int i=a;i<=b;++i) #define rrep(i,a,b) for(int i=b-1;i>=a;--i) #define rrep1(i,a,b) for(int i=b;i>=a;--i) typedef long long LL; using namespace std; /*===========================================*/ const int maxn = 1e5 + 5; LL sum[maxn]; int main() { rep(i, 1, maxn) sum[i] = sum[i - 1] + 1LL * i * i; int T; scanf("%d", &T); while (T--) { long long n; scanf("%lld", &n); long long t = n / 2; if (n == 2) printf("1\n2 1\n1\n2 1\n"); else if (n == 3) printf("5\n2 3 1\n2\n2 1\n1 3\n"); else { printf("%lld\n", (n - 1) * (n - 1) + 2 * (sum[n - 2] - sum[n - 1 - t]) + (n & 1 ? (n - 1 - t) * (n - 1 - t) : 0)); printf("%lld", n - 1); rep(i, 2, t) printf(" %d", i + 1); printf(" 1 %lld", n); rep(i, t + 2, n) printf(" %d", i - 1); printf(" 2\n"); printf("%lld\n", n - 1); rep1(i, 2, t) printf("%d %lld\n", i, n); rrep(i, t + 1, n) printf("%d 1\n", i); printf("%lld 1\n", n); } } }
Codeforces Round #696 (Div. 2) 2021-01-19
标签:gre back 后缀 有序 数值 序列 code print else
原文地址:https://www.cnblogs.com/GZ-NEW/p/14337421.html