Codeforces Round #786 (Div.3) A-D
A. Number Transformation
题意:
给定两个整数x,y;定义操作:若x可以经过a次乘以数字b的操作后得到y,则输出a b,否则输出两个0;
例如:
x=3;y=75
75=3*5*5
(3通过2次乘以5的操作后得到75,此时a=2,b=5)
a=2;b=5
只需要判断y是否是x的倍数,如果是则输出1和y/x,否则输出两个0;
核心代码:
printf(y%x==0?"%d %d\n":"0 0\n",1,y/x);
B. Dictionary
题意:
规律如下:
ab序号为1
ac序号为2
……
az序号为25
ba序号为26
……
zx序号为649
zy序号为650
询问输入一个存在的单词,输出它的序号
不难发现,此题就是两个字母a-z
的按顺序组合,但是若两个字母相同则不计算在内。
核心代码:
map<string,int> mp;
int p=1;
for(char i='a';i<='z';i++){
for(char j='a';j<='z';j++){
if(i!=j){
string s="";
s+=i;
s+=j;
mp[s]=p++;
}
}
}
C. Infinite Replacement
题意:
给定两个字符串s,t;
s中只包含字符
a
;可以无限次的将s中的字符
a
替换成字符串t求结果所得的所有可能的字符串组合
由样例不难得出:
1、当 t 只有一个字符a
时,则只有一种结果,因为无论怎样替换都只能得到s。
2、当 t 包含字符a
,且长度大于1时,s可以替换成长度大于s的若干字符串。因为替换后还包含了a
s = aaa
;
t = aa
;替换后:
aaaa、aaaaa、aaaaaa……
t中包含a也包含其他字符的情况与此相同,但要求长度大于1
3、当 t 不包含a
时,可以随意将s中的若干个a
都替换成 t,视为一种情况;
s = a
t = b
则有两种结果:
a
、b
推理:
s = aa
t = b
则有四种结果:
aa
、ba
、ab
、bb
s = aaa
t = b
则有:
aaa
baa
、aba
、aab
bba
、bab
、abb
bbb
不难发现答案为组合数
( ∏ i = 1 s . l e n g t h ( ) C s . l e n g t h ( ) i ) + 1 (\prod_{i=1}^{s.length()}C_{s.length()} ^i) +1 (i=1∏s.length()Cs.length()i)+1
其他t中不包含a
的情况视同
核心代码:
组合数,此处用杨辉三角来求得
此时
c[m][n]
表示
C m n C_m^n Cmn
c[0][0]=1;
c[1][0]=1;
c[1][1]=1;
for(int i=2;i<=51;i++){
for(int j=0;j<=i;j++){
if(j==0||j==i) c[i][j]=1;
else c[i][j]=c[i-1][j]+c[i-1][j-1];
}
}
//判断t中是否存在字符a和其他(other)字符
bool a_=false,o_=false;
for(int i=0;i<t.length();i++){
if(t[i]=='a') a_=true;
if(t[i]!='a') o_=true;
}
//若a字符和其他字符同时存在,则有无穷多解
if(a_==true&&o_==true){
cout <<-1<<endl;
}
//若a存在,则判断t长度是否大于1:若大于1则无穷多解,否则只有一种解
else if(a_==true&&o_==false){
if(t.length()>1){
cout <<-1<<endl;
}
else cout <<1<<endl;
}
//其他结果则是组合数的自动求和+1
else{
long long ans=0;
for(int i=1;i<=s.length();i++){
ans+=c[s.length()][i];
}
cout <<ans+1<<endl;
}
此题注意范围,需开long long
D. A-B-C Sort
题意:
有三个数组a,b,c
现给定a
经过:
每次将a中尾部元素放入b数组的中部:
1、若b数组元素个数为奇数,则可以将a尾部元素放入最中间元素的左右皆可。
2、若b数组元素个数为偶数,则必须将a尾部元素放入最中间使得该元素放入后左右元素个数相同。直到a数组为空
再将b数组中元素从中间取出按顺序放入c数组的尾部:
1、若b数组元素个数为偶数个,则可任意将b数组最中间的两个任意放入c。
2、若b数组元素个数为奇数个,则必须将b数组最中间元素放入c
求问:
能否得到c数组按不降序排列
我们可以逆向思维来看,c数组不降序排列,说明b数组中从最中间元素到最外层元素不降序排列
例如:
b[4] = {3,3,1,5}
由最中间层为
b[2]和b[1]
到最外层为
b[0]和b[3]
只需要求层层不降序
那怎么从a数组放入b数组呢?
从a数组末尾元素,每两个构成一层,a数组从后往前,构成外层至内层;
例如:
a[4]={3,1,5,3}
两次操作后
a = 3 1
b =
3
5
再两次操作后
a = null
b =
3
1 35
则只需判断这一层的最大值是否大于上一层的最小值
核心代码:
#include<bits/stdc++.h>
using namespace std;
int a[200007];
void solve(){
int n;
cin >>n;
//我的数据是从1开始读入,有些人会从0开始读入
for(int i=1;i<=n;i++){
cin >>a[i];
}
//若a数组只有一个元素,则必定可以构成不降序c
if(n==1){
cout <<"YES"<<"\n";
return;
}
//最外层的最小值
int x=min(a[n],a[n-1]);
//判断每一层
for(int i=n-2;i>=2;i-=2){
//若这一层的最大值大于上一层的最小值,则不能得到不降序c
if(max(a[i],a[i-1])>x){
cout <<"NO"<<"\n";
return;
}
//记录这一层的最小值然后进入下一层
x=min(a[i],a[i-1]);
}
//若a数组为奇数,则会有a[1]没有进入循环去判断
if(n&1){
if(a[1]>x){
cout <<"NO"<<"\n";
return;
}
}
//循环跑完,没有不符合的,则有不降序数组c
cout <<"YES"<<endl;
}
int main(){
int T;
cin >>T;
while(T--){
solve();
}
return 0;
}
最后放一个完整代码,可以评价一下我的代码风格。我个人觉得还不错,但只是个人觉得。