- cf #787 Div.3
- [A. Food for Animals](https://codeforces.com/contest/1675/problem/A)
- [B. Make It Increasing](https://codeforces.com/contest/1675/problem/B)
- [C. Detective Task](https://codeforces.com/contest/1675/problem/C)
- 题意
题目大致含义:商店有三种饲料,一种只给猫猫、一种只给狗狗、一种猫猫狗狗都可以用,它们的数量为a,b,c。猫猫数量为x,狗狗数量为y,问能否让所有猫猫狗狗都吃上一包饲料
- 题解
一眼简单贪心,分别看猫猫和狗狗够不够就好
- 代码
#includeusing namespace std; bool ok(int a,int b,int c,int x,int y){//因为正面情况较多,那么枚举举反面例子 if(a >t; while (t--){ int a,b,c,x,y; cin>>a>>b>>c>>x>>y; if(ok(a,b,c,x,y))cout<<"YES"< B. Make It Increasing
- 题意
给定一组数,每个数都可以进行向下除2的操作,问最少需要经过多少次操作可以使得这组数严格单调递增
- 题解
一眼贪心,操作只能把数变小但要求数列单增,那么从后向前看,最后一个数必然不用去操作了,向前走一旦这个数比后一个数大就操作它减小,这样操作一定是最优解。为什么这是最优解呢?要把这组数变成递增有n种方案,每一种方案中都是最后一个数最大,那么在这n种方案中如果这种方案的最后一个数最大那么它前面数所操作的次数最少,故当最后一个数不操作时操作次数最少。
- 代码
#includeusing namespace std; const int N=35; long long f(int n,int a[]){ if(n==1)return 0;//1个数不用操作 long long res=0; for(int i=n-2;i>=0;--i){//从后往前遍历操作 while (a[i]>=a[i+1]){//如果这个数大于后一个数,需要操作 if(!a[i])return -1;//如果这个数为0,那么再也没办法使它变小了,故无解 a[i]/=2;//除2 res++;//次数++ } } return res; } int main() { int t; cin>>t; while (t--){ int n,a[N]; cin>>n; for (int i = 0; i < n; ++i) cin>>a[i]; cout< C. Detective Task
题意
大致题意:给定一个只含有01?三种字符的字符串,表示一列一次进画室的人的回答,0代表没看到画,1表示看到了画,?表示不记得了。其中只有那一个偷画人可以说谎,其他人必须说真话,找出嫌疑人的个数
题解
通过样例得到了一个规律:从第一个0开始向前走遇到的第一个1之间所包含的字符数就是嫌疑人数。同时10的转换只会出现一次
简略证明:
1 1 1 ? 0 0 0
这组字符中,第一个出现的0和从0向前的第一个1都用下划线画出来了,分别记作p0和p1,我们证明p0之后以及p1之前不会再说谎。(反证法)
首先有个前提就是找到了这个10转换那么0之后全是0,1之前全是1。假设加粗的0是嫌疑人说谎,也就是说加粗位置是1画存在,同时之前的人全是真话,那么下划线0位置是真话,画是不存在的,换言之这幅画在之前消失了,矛盾,假设不成立,故加粗位置不可能是嫌疑人。即p0之后的人不是嫌疑人
同理,p1前的人不可能是嫌疑人。
那么只有p1和p0之间的人可能是嫌疑人,故答案是p0-p1+1
代码
#include#include using namespace std; int f(string &s){ int pos_last_0=s.size()-1,pos_first_1=0;//初始化,如果0不存在那么最后一位置为p0,如果1不存在那么第一个位置位置为p1 for(int i=0;i 0;--i){//找p1 if(s[i]=='1')break; } pos_first_1=i; return pos_last_0-pos_first_1+1; } int main() { int t; cin>>t; while (t--){ string s; cin>>s; cout<



