Educational Codeforces Round 90 (Rated for Div. 2)
A.Donut Shops
题意:
a,b,c分别代表买1个甜甜圈要a元,但如果一盒一盒买只要c元,一盒有b个甜甜圈
购买方式只能选一种
假设要买x个甜甜圈,第一种购买方式要a*x元,第二种购买方式要((x+b-1)/b)c元
问你要买x个甜甜圈使第一种方式付的钱严格少于第二种,如果没有输出-1;
再问你要买y个甜甜圈使第二种方式付的钱严格少于第一种,如果没有输出-1;
思路:
当我买1个甜甜圈的时候第一种方式能比第二种方式贪心不少
当我买b个甜甜圈的时候第二种方式能比第一种方式贪心不少
所以判断a与c的大小
再判断ab与c的大小
代码:
#include <bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
const int maxn = 3e5 + 5;
const ll mod = 1e9 + 7;
const ll inf=0x3f3f3f3f;
const ld pi=acos(-1.0);
ll n,m,a,b,c,x,y,t;
void run(){
cin>>a>>b>>c;
if(a<c)cout<<1<<" ";
else cout<<-1<<" ";
if(a*b<=c)cout<<-1<<'\n';
else cout<<b<<'\n';
}
int main(){
#ifdef haosao
freopen("main.h", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
run();
return 0;
}
B.01 Game
题意:
Alice and Bob
给你一个由01组成的字符串S;
当01相邻的时候,player可以进行一次操作,删除这个相邻的01;
谁不能操作谁就输;
Alice先手。
问Alice能不能赢。
思路:
当S不能操作的时候只有三种,全1,全0,S为空;
显然,只要S存在0并且存在1,那么player就能进行操作。
算出最多的操作次数,若为奇数,Alice赢,输出DA,反之输出NET。
显然操作次数是min(0.size(),1.size());
代码:
#include <bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
const int maxn = 3e5 + 5;
const ll mod = 1e9 + 7;
const ll inf=0x3f3f3f3f;
const ld pi=acos(-1.0);
ll n,m,a,b,c,x,y,t;
string s;
void run(){
cin>>s;
a=b=0;
n=s.size();
for(int i=0;i<n;i++){
if(s[i]-'0')a++;
else b++;
}
a=min(a,b);
if(a%2)cout<<"DA\n";
else cout<<"NET\n";
}
int main(){
#ifdef haosao
freopen("main.h", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
run();
return 0;
}
C.Pluses and Minuses
题意:
给你一个由‘+’和‘-’组成的字符串S;
然后通过这个伪代码,输出res;
res = 0
for init = 0 to inf
cur = init
ok = true
for i = 1 to |s|
res = res + 1
if s[i] == '+'
cur = cur + 1
else
cur = cur - 1
if cur < 0
ok = false
break
if ok
break
思路:
通过前缀和直接算res,省掉重复的运算。
O(n);
代码:
#include <bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
const int maxn = 1e6 + 5;
const ll mod = 1e9 + 7;
const ll inf=0x3f3f3f3f;
const ld pi=acos(-1.0);
ll n,m,a[maxn],b,c,x,y,t;
string s;
void run(){
cin>>s;
n=s.size();
for(int i=0;i<n;i++){
if(s[i]=='+')a[i+1]=a[i]+1;
else a[i+1]=a[i]-1;
}
ll ans=0;
ll now=0;
for(int i=1;i<=n;i++){
if(now+a[i]<0){
ans+=(-1*a[i]-now)*i;
now=-a[i];
}
ans++;
}
cout<<ans<<'\n';
}
int main(){
#ifdef haosao
freopen("main.h", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
run();
return 0;
}
D.Maximum Sum on Even Positions
题意:
一个长度为n(0-n-1)的数组;进行一次反转子数组的操作,使得偶数位上的数之和最大。
思路:
把这个数组转化成奇数位和偶数位差的新数组,
显然有两种:1.奇数位与之之前的差;2.奇数位与之之后的差。
问题就转化成了最大字段和。
代码:
#include <bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;
const ll inf=0x3f3f3f3f;
const ld pi=acos(-1.0);
ll n,m,a[maxn],b,c,x,y,t;
string s;
void run(){
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
ll ans=0;
for(int i=0;i<n;i+=2)ans+=a[i];
ll tmp=0;
ll max1=0,max2=0;
for(int i=1;i<n;i+=2){
tmp+=a[i]-a[i-1];
max1=max(max1,tmp);
if(tmp<0)tmp=0;
}
ll ttp=0;
for(int i=1;i<n-1;i+=2){
ttp+=a[i]-a[i+1];
max2=max(max2,ttp);
if(ttp<0)ttp=0;
}
ans+=max(max1,max2);
cout<<ans<<'\n';
}
int main(){
#ifdef haosao
freopen("main.h", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
run();
return 0;
}
E.Sum of Digits(我的菜鸡做法)
题意:
首先定义f(x)为x在十进制下各个位上数的和。
输入:t,n,k
t组测试用例
1<=n<=150;0<=k<=9;
对于每组测试用例
输出一个不带前导0的整数x,使得f(x)+ f(x + 1)+⋯+ f(x + k)= n。
如果没有x满足,输出-1;如果有多组x满足条件,输出最小的x;
思路:
没有思路,我被打死。
首先,很显然的能发现当k=0时,n不管为多少,x都能找到最小的数,格式为n`999999;
也就是用9把n填满。
然后,我实在没有想法(主要是没好的想法,wa3),就开始尝试打表,毕竟所有答案只有1500个,当k=1时,n=1-150:0,-1,1,-1,2,-1,3,-1,4,9,5,19,6,29,7,39,8,49,18,59,28,69,38,79,48,89,58,189,68,289,78,389,88,489,98,589,198,689,298,789,398,889,498,989,598,1989…很明显的规律
同理我打出了k=2,k=3;
当我打完k=3的时候发现,n=150时,ans已经小于1e5;
最后我就暴力打表1e5求出k>=3的情况,特判k=1,k=2,k=0
代码:
#include <bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
const int maxn = 2e5 + 5;
const ll mod = 2e18 + 7;
const ll inf=0x3f3f3f3f;
const ld pi=acos(-1.0);
ll n,m,c,x,y,t,k;
ll a[10][300],b[maxn];
//ll a[20]={0,1,3,6,10,15,21,28,36,45,46,48,51,55,60,66,73,81,90,100};
vector<ll>g[10];
ll go(int num){
ll res=0;
while(num){
res+=num%10;
num/=10;
}
return res;
}
string s;
void run(){
cin>>n>>k;
if(k==0){//特判k=0
if(n%9){
cout<<n%9;
n-=(n%9);
}
while(n){
cout<<9;
n-=9;
}
cout<<'\n';
return;
}
cout<<a[k][n]<<'\n';
}
int main(){
#ifdef haosao
freopen("main.h", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
std::ios::sync_with_stdio(false);
for(int i=1;i<=150;i++){
for(int j=0;j<10;j++)
a[j][i]=-1;
}
for(int i=0;i<=100100;i++){
b[i]=go(i);
}
//暴力求出1e5
for(int x,i=0;i<100000;i++){
x=0;
for(int j=0;j<10;j++){
x+=b[i+j];
if(x>150)break;
if(a[j][x]!=-1)continue;
a[j][x]=i;
}
}
ll tmp=0;
//特判k=2
for(int i=44;i<=148;i++){
tmp=1;
while(a[1][i]/tmp){
tmp*=10;
}
tmp/=10;
if(a[1][i]/tmp==9){
a[1][i+2]=a[1][i]+tmp*10;
}else{
a[1][i+2]=a[1][i]+tmp;
}
}
//特判k=3
for(int i=45;i<=147;i+=3){
tmp=1;
while(a[2][i]/tmp){
tmp*=10;
}
tmp/=10;
if(a[2][i]/tmp==9){
a[2][i+3]=a[2][i]+tmp*10;
}else{
a[2][i+3]=a[2][i]+tmp;
}
}
// for(int i=1;i<=150;i++){
cout<<a[1][i];
// for(int j=0;j<10;j++){
// cout<<a[j][i]<<" ";
// }
// cout<<'\n';
// }
cin>>t;
while(t--)
run();
return 0;
}