Codeforces Round #723 (Div. 2)Codeforces Round #723 (Div. 2)

B. I Hate 1111

题意:能不能把一个数写成11,111,1111,11111……这些数的加和,如果可以的话输出YES,如果不能就输出NO。

思路:这个题一个方面是它仅仅是个B题,直接暴力就行,再就是观察题目,1111=11*10+11,11111=111*100+11,这样看来最后就是计算11和111能不能表示它。

 

 代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 using namespace std;
 7 int main(){
 8     int t;
 9     scanf("%d",&t);
10     while(t--){
11         int n;
12         scanf("%d",&n);
13         int p=0;
14         int s=11*111-11-111;
15         if(n>s){
16             printf("YES\n");
17             continue;
18         }
19         int flag=0;
20         while(p*111<=n){
21             n-=p*111;
22             if(n%11==0){
23                 flag=1;
24                 break;
25             }
26             n+=p*111;
27             p++;
28         }
29         if(flag==1){
30             printf("YES\n");
31         }else{
32             printf("NO\n");
33         }
34     }
35 }
View Code

 

 C1. Potions (Easy Version)

题意:就是在一组数中从左往右选取生命值的变动,选取a1,就+a1,中途不能出现0和负数,问最多可以选择多少个

思路:用dp,主要就是需要注意一下,如果是小于等于0了,就要给他赋值-∞,这样才能保证不出现后面救活的现象

代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #define int long long
 7 using namespace std;
 8 int dp[2500][2500];
 9 int a[2500];
10 signed main(){
11     int n;
12     scanf("%lld",&n);
13  
14     for(int i=1;i<=n;i++){
15         scanf("%lld",&a[i]);
16     }
17  
18     for(int i=0;i<=n;i++){
19         for(int j=0;j<=n;j++){
20             dp[i][j]=0;
21         }
22     }
23     if(n==1){
24         if(a[1]>=0){
25             printf("1\n");
26         }else{
27             printf("0\n");
28         }
29         return 0;
30     }
31     dp[1][1]=a[1];
32     int ans=0;
33     for(int i=2;i<=n;i++){
34         for(int j=1;j<i;j++){
35             if(dp[i-1][j]<0&&dp[i-1][j-1]<0){
36                 dp[i][j]=-1000000000LL;
37             }else if(dp[i-1][j]<0){
38                 dp[i][j]=dp[i-1][j-1]+a[i];
39             }else if(dp[i-1][j-1]<0){
40                 dp[i][j]=dp[i-1][j];
41             }else{
42                 dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+a[i]);
43             }
44             if(dp[i][j]>=0){
45                 ans=max(ans,j);
46             }
47         }
48         if(dp[i-1][i-1]>=0){
49             dp[i][i]=dp[i-1][i-1]+a[i];
50         }else{
51             dp[i][i]=-1000000000LL;
52         }
53         if(dp[i][i]>=0){
54             ans=max(ans,i);
55         }
56     }
57     printf("%lld\n",ans);
58 }
View Code

 

C2. Potions (Hard Version)

题意:和c1题意一样,只不过是复杂度变成了2e5

思路:用优先队列维护一个小顶的优先队列,然后从前往后入队列,如果队列的总和变成了负数,那么就减掉第一个数,以此类推

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<vector>
 7 #include<queue>
 8 using namespace std;
 9 const int maxx=2e5+10;
10 int a[maxx];
11 vector<int>b;
12  
13 int main(){
14     int n;
15     scanf("%d",&n);
16     for(int i=0;i<n;i++){
17         scanf("%d",&a[i]);
18     }
19     priority_queue<int, vector<int>, greater<int>> p;
20     long long int sum=0;
21     int ans=0;
22     for(int i=0;i<n;i++){
23         sum+=a[i];
24         p.push(a[i]);
25         while(sum<0){
26             sum-=p.top();
27             p.pop();
28         }
29         int sp=p.size();
30         ans=max(ans,sp);
31     }
32     printf("%d\n",ans);
33 }
View Code

 

一个是大胆暴力和一个数学定理,一个是思路问题,dp和反悔贪心,如果一开始的方向就对了,那么C1过了C2的话就直接一份代码秒过

 

posted @ 2021-06-11 11:22  bonel  阅读(61)  评论(0编辑  收藏  举报