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