Gym 102263 - ArabellaCPC 2019 题解
A - Is It Easy ?(签到题)
#include<iostream> #include<algorithm> using namespace std; int main() { int n,m; cin>>n>>m; cout<<n*m; }
B. Road to Arabella(博弈论)
思路:
只有$n-k≤1$并且$n$不是偶数的情况下,后手才能赢
#include<iostream> #include<algorithm> using namespace std; int main() { int t,n,k; cin>>t; while(t--){ cin>>n>>k; if((n==k||n==k+1)&&n%2==0) cout<<"Ayoub"<<endl; else cout<<"Kilani"<<endl; } }
C. Check The Text(模拟)
#include<iostream> #include<algorithm> using namespace std; int main() { string s1,s2="",s; int n,t; cin>>n; getchar(); getline(cin,s1); cin>>t; int flag=0; while(t--){ cin>>s; if(s[0]=='B'){ if(s2.size()) s2.pop_back(); } else if(s[0]=='C') flag^=1; else if(s[0]=='S') s2+=" "; else{ if(flag==0) s2+=s; else s2+=(s[0]-'a'+'A'); } } if(s2.compare(s1)==0) cout<<"Correct"; else cout<<"Incorrect"; }
D. Meeting Bahosain(思维+GCD)
思路:
假设我们想用数组$b$中的元素去表示一个数$x$,就可以写成$x=k1*b[1]+k2*b[2].....$也可以写成$x=k*gcd(b[1],b[2]...b[n])$
那么我们只要需要数组$a$中,任意两个元素之间的差值(可以用$gcd(a[1],a[2]...a[n])$来表示)是否能整除$gcd(b[1],b[2]...b[n])$即可
#include<iostream> #include<algorithm> using namespace std; int main() { int n,m,g1,g2,temp; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&temp); if(i==1) g1 = temp; else g1=__gcd(g1,temp); } for(int i=1;i<=m;i++){ scanf("%d",&temp); if(i==1) g2=temp; else g2=__gcd(g2,temp); } if(g1%g2==0||n==1) printf("Yes\n"); else printf("No\n"); return 0; }
G. Card Game(数学期望)
思路:
最后的期望公式为:$\frac{\sum i*(i-1)}{n},2≤i≤n$
#include<iostream> #include<algorithm> #include <iomanip> using namespace std; int main() { int n; cin>>n; long double ans=0,y=n; for(int i=1;i<=n;i++){ long double x=i; ans+=x*(x-1)/y; } cout<<fixed<<setprecision(10)<<ans; }
H. Steaks(思维)
思路:
当$n≥2*k$时,只要花$10$分钟就好了,否则一块牛排需要煎$5$分钟
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; int main() { ll n,m; cin>>n>>m; if(n>2*m) cout<<(n+m-1)/m*5; else cout<<10; }
I. Bashar and Hamada(思维)
思路:
有点类似于$2018$年焦作站的一道题
先将数组排序,然后一大一小放置即可
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=3e5+10; ll a[maxn]; int main() { ll n,ans=0,last,flag=0; scanf("%lld",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); sort(a+1,a+1+n); last=ans=a[n]-a[1]; int l=2,r=n-1; cout<<ans<<" "; while(l<=r){ if(flag==0){ ans+=last; l++; } else{ last+=a[r]-a[l-1]; ans+=last; r--; } cout<<ans<<" "; flag^=1; } return 0; }
J. Thanos Power(DP)
思路:
想要得到第$i$位上的数$x$有两种方法
①直接加$x$次$10^{i}$
②先得到$10^{i+1}$,再用减法得到,需要进行$10-x+1$次操作
我们假设$dp[0][i]$,是以第①种方式得到$x$;$dp[1][i]$是以第二种方式得到$x$
那么递推式就为:
$dp[0][i]=s[i]+min(dp[0[[i-1[,dp[1][i-1])$
$dp[1][i]=10-s[i]+min(dp[0][i-1]+1,dp[0][i-1]-1)$
因为上一位是由方式①得到,我们还需要在上一位加上一再通过减法得到;如果上一位是由方式二得到,我们再上一位加上一,上一位就可以少进行一次减法,所以减一
#include<iostream> #include<algorithm> using namespace std; const int maxn=1e5+10; int dp[2][maxn]; string s; int main() { cin>>s; dp[0][0]=s[0]-'0'; dp[1][0]=10-(s[0]-'0')+1; for(int i=1;i<s.length();i++){ dp[0][i]=s[i]-'0'+min(dp[0][i-1],dp[1][i-1]); dp[1][i]=10-(s[i]-'0')+min(dp[0][i-1]+1,dp[1][i-1]-1); } cout<<min(dp[0][s.length()-1],dp[1][s.length()-1]); }
M. Two Operations(思维)
思路:
统计每个字符的个数,从小到大(除了z)逢$2$向更大的字符进一位
#include<iostream> #include<algorithm> #include<map> using namespace std; map<int,int> m; int main() { string s; cin>>s; for(int i=0;i<s.length();i++) m[s[i]-'a']++; for(int i=0;i<25;i++){ int num=m[i]; m[i+1]+=num/2; m[i]=num%2; } for(int i=25;i>=0;i--) for(int j=1;j<=m[i];j++) printf("%c",'a'+i); return 0; }