比赛链接:https://codeforces.com/contest/1430
A:https://codeforces.com/contest/1430/problem/A
题意:给你一个n,让你输出三个数a,b,c使得3 * a+5 * b+7 * c=n。如果不存在的话,输出-1就好。
思路:看一下数据范围,大暴力就好。(我写的时候根本不敢暴力,最后抱着必WA的心态交的)
//team yglance+xhwl+TTD //author: CN.TTDragon #include<bits/stdc++.h> typedef long long ll; const ll mod=1e9+7; const ll maxn=1e5+7; const double pi=acos(-1); using namespace std; int main() { ios::sync_with_stdio(false); //freopen("in.in","r",stdin); //freopen("mine.out","w",stdout); int t; cin>>t; while(t--) { int n; cin>>n; int a=0,b=0,c=0; if(n%3==0) { a=n/3; cout<<a<<" "<<b<<" "<<c<<endl; continue; } if(n%5==0) { b=n/5; cout<<a<<" "<<b<<" "<<c<<endl; continue; } if(n%7==0) { c=n/7; cout<<a<<" "<<b<<" "<<c<<endl; continue; } int f=0; for(a=n/3+1;a>=0;a--) { for(b=0;b<=201;b++) { for(c=0;c<=143;c++) { if(a*3+b*5+c*7==n) { cout<<a<<" "<<b<<" "<<c<<endl; a=-5; b=2000; c=3000; f=1; break; } } } } if(f==0) { cout<<"-1"<<endl; } } return 0; }
B:https://codeforces.com/contest/1430/problem/B
题意:给你n个装了水的水桶(容量无限),有k次机会可以相互倒而且数量任意,叫你最大化含水量最多和最少的水桶的差值。
思路:求和就好,把最大的k桶水都放进这k个桶中一个里,它和其他为零的桶的差值必然最大
//team yglance+xhwl+TTD //author:CN.TTDragon #include<bits/stdc++.h> typedef long long ll; const ll mod=1e9+7; const ll maxn=2e5+7; const double pi=acos(-1); using namespace std; ll a[maxn]; int main() { ios::sync_with_stdio(false); //freopen("in.in","r",stdin); //freopen("mine.out","w",stdout); int t; cin>>t; while(t--) { int n,k; cin>>n>>k; for(int i=0;i<n;i++) { cin>>a[i]; } sort(a,a+n); for(int i=n-2;i>=0&&k;i--) { a[n-1]+=a[i]; a[i]=0; k--; } cout<<a[n-1]<<endl; } return 0; }
C:https://codeforces.com/contest/1430/problem/C
题意:给你1-n的序列,你可以任意选择两个进行求和,然后删除它们,然后又把它们的平均值加回来。要最后回剩下一个数,要你最小化这个数,并展示过程。
思路:不难发现答案必然为2。你把n-2和n删除后,可以得到n-1,然后两个n-1变成1个。这个时候比最大值恰好小1的数是不存在。你的用n-1与n-3来获取n-2,不断地把X(当前最大值)与X-2相消以获得X-1,最后恰好可以变成1与3,得到答案2。我这个办法除了第一步和第二步特殊外,其他都很常规。所以需特判掉2。
例子:
//team yglance+xhwl+TTD //author: CN.TTDragon #include<bits/stdc++.h> typedef long long ll; const ll mod=1e9+7; const ll maxn=2e5+7; const double pi=acos(-1); using namespace std; int main() { ios::sync_with_stdio(false); //freopen("in.in","r",stdin); //freopen("mine.out","w",stdout); int t; cin>>t; while(t--) { int n; cin>>n; if(n==2) { cout<<2<<endl; cout<<1<<" "<<2<<endl; continue; } cout<<2<<endl; cout<<n<<" "<<n-2<<endl; cout<<n-1<<" "<<n-1<<endl; for(int i=n-1;i>=3;i--) { cout<<i<<" "<<i-2<<endl; } } return 0; }
D:https://codeforces.com/contest/1430/problem/D
题意:给你一个长度为n的01串,每次操作你可以任意删除一个元素,然后把当前串的最大相同前缀(这里指的就是所有连续的0和1)删除,问你这个串最多需要多少次操作才能删除到成为一个空串。
思路:不难发现这道题中连续的串意义很大,如果形如111的串在最前面(在最前面2个就好),那么这次删除就可以只损失这些1,而不损失任何0。如果形如111的串不在最前面(不在最前面3个才有统计的意义,具体原因请继续看),那么当最前面是形如010的情况时,可以在111里面删除一个1,使损失更小,不会使得前面损失两种不同的数。这么一来就很清楚了,首先我们要欲处理字符串中的连续部分的长度,哪怕长度为1也是需要的。然后就是计算答案的过程。如果最前面的是一个比1大的数,说明形如11……的串在前面,这次删除我们可以使另一种数不被删除。但是如果是形如010……这样的最前面两个不相同且为1。这时我们说到的形如111的串不在最前面就派上用场了,我们可以在111……里面删除一个,然后前面就只会损失一种数,但是如果被删除后恰好为2了,就不能再用它,否则它为最前面的时候就要给后面添麻烦了。
至此代码也就写出来了。对于寻找长度大于3等于的连续串,我们可以用队列来帮助我们。
//team yglance+xhwl+TTD //author: CN.TTDragon #include<bits/stdc++.h> typedef long long ll; const ll mod=1e9+7; const ll maxn=2e5+7; const double pi=acos(-1); using namespace std; string s ; ll a[maxn];//记录s中的连续串长度 ll ans=0; queue<ll > que;//记录长度大于等于3 的连续串在a中的位置 int main() { ios::sync_with_stdio(false); //freopen("in.in","r",stdin); //freopen("mine.out","w",stdout); int t ; cin>>t; while(t--) { while(!que.empty())//队列清空 { que.pop(); } int n; cin>>n; cin>>s; int cnt=0;//记录连续串的数量 int p=0;//记录连续串的头部 ans=0; for(int i=0;i<n;i++) { if(s[i]==s[p]) { continue; } else { if(i-p<=2)//长度为 1或2 、 3+的连续串处理方法不同 { a[cnt++]=i-p; p=i; } else//大于等于3,它们需要入队 { a[cnt++]=i-p; que.push(cnt-1); p=i; } } } a[cnt++]=n-p;//最后一组别忘记 if(n-p>=3) { que.push(cnt-1); } // for(int i=0;i<cnt;i++) // { // cout<<a[i]<<" "; // } // cout<<endl; for(int i=0;i<cnt;) { if(a[i]==1)//如果最前面是个单独串(单独字符) { if(i==cnt-1)//额外判断一下是不是最后一个 { ans++; i++; } else { if(que.empty() !=1)//队列不为空,去后面找长度大于等于3的串来帮忙 { a[que.front()]--; if(a[que.front()]==2)//长度变成2了,失去作用! { que.pop(); } i++; ans++; } else//队列空了 { if(a[i+1]==1)// 最前面两个不相同且为1 { ans++; i+=2;//这次要位移两个单位 } else//第二位开始有一个不为长度 1 的连续串 { ans++; a[i+1]--;//记得把长度减去 i+=1; } } } } else//最前方长度不为1。 { ans++; i++; } while(que.empty() !=1 && que.front()<=i)//这里要注意,很可能我们删除的最前面的串就是队列里的串。 { que.pop(); } } cout<<ans<<endl; } return 0; }
写在最后:
人和人之间学习能力的差距怎么这么大?