A Make Equal With Mod
题意:
给出一个数组,可以给出一个不小于2的数K,令数组中的每个数对其进行取模运算,问能否操作至数组中每个数相同
思路:
因为K不能等于1,所以可以分成数组中 有1 和 无1 两种情况
对于无1的情况,可以从最大数开始对其自身取模变为0,易得最后数组中所有数都将为0,一定满足题意
对于有1的情况,若数组可满足题意,则最后全为1,所以操纵策略为从最大数开始对 自身-1 的数取模,此时就可以发现,若出现了两个相差1的数,则一定会出现0,故无法达成条件
将数组排序之后对三种情况判断即可
AC代码:
#include<bits/stdc++.h>
using namespace std;
int t,n;
int arr[100005];
void solve(){
cin>>n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
sort(arr,arr+n);
int f1 = true;
int f2 = true;
int f3 = false;
if(arr[0]==1) f2 = false;
for(int i=1;i<n;i++){
if(arr[i]!=arr[i-1]){
f1 = false;
//break;
}
if(arr[i]==1){
f2 = false;
}
if((arr[i]-arr[i-1])==1){
f3 = true;
}
}
if(f1){
//cout<<"1: ";
cout<<"YES"<<endl;
return ;
}
if(f2){
//cout<<"2: ";
cout<<"YES"<<endl;
return ;
}
if(!f2 && f3){
//cout<<"3: "<<endl;
cout<<"NO"<<endl;
return ;
}
if(!f2 && !f3){
cout<<"YES"<<endl;
return ;
}
}
int main(){
cin>>t;
while(t--){
solve();
}
return 0;
}
B Game on Ranges
题意 :
一个数组中包含一个元素(l,r) (范围),可以选取范围中的一个数d,令(l,r)变为(l,d-1) (d+1,r)当d-1>=l(或d+1>=r)时,其消失,现在题目中给出了每次选取d的范围,要求反推d
思路:
对于给出的范围(x,x),据题意可知d=x,也就只需从小范围往大范围推导d,每次推导出来的d进行标记,此时大范围中可用的d就越来越少了,即可推出答案
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 1003
struct interval{
ll l,r,num;
}a[maxn],b[maxn];
ll t,n,ans[maxn];
bool cmp(interval a,interval b)
{
if(a.l!=b.l)return a.l<b.l;
else return a.r>b.r;
}
int main()
{
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].l>>a[i].r;
a[i].num=i;
b[i]=a[i];
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
if(a[i].l==a[i+1].l&&i!=n)ans[a[i].num]=a[i+1].r+1;
else if(a[i].r==a[i+1].r&&i!=n)ans[a[i].num]=a[i+1].l-1;
else if(a[i].l==a[i].r)ans[a[i].num]=a[i].l;
}
for(int i=1;i<=n;i++) cout<<b[i].l<<" "<<b[i].r<<" "<<ans[i]<<endl;
cout<<endl;
}
return 0;
}
C Buy an Integer
思路:注意答案最大到1e9,分析题目给出的函数发现时单增,所以采用二分法就好
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a,b,x;
int t;
int weishu(int xx){
int cnt = 0;
while(xx){
cnt++;
xx/=10;
}
return cnt;
}
void solve(){
cin>>a>>b>>x;
// int mai = x/a; //cout<<"max: "<<mai<<endl;
// if(mai == 0){cout<<0; return ;}
// if(1000000000*a+b*9<=x){cout<<1000000000; return ;}
int l = 1,r = 1000000000,mid;
while(l<=r){
mid=(l+r)>>1;
if(mid*a+weishu(mid)*b>x) r=mid-1;
else l=mid+1;
}
cout<<r;
}
signed main(){
t=1;
while(t--){
solve();
}
return 0;
}
D String Formation
思路:记录翻转的次数cnt,根据(cnt%2)来改变操作,最后也是依此决定是否翻转一次
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
string a;
cin>>a;
int t;
cin>>t;
int cnt=0;
while(t--){
int x1;
cin>>x1;
if(x1 == 1){
cnt++;
}
else{
int x2; string add;
cin>>x2;
cin>>add;
if(cnt%2){
if(x2==1) a += add;//cout<<"# "<<a<<endl;
else a = add+a;//cout<<"# "<<a<<endl;
}
else{
if(x2==1) a = add+a;// cout<<"# "<<a<<endl;
else a += add;// cout<<"# "<<a<<endl;
}
}
}
if(cnt%2){
reverse(a.begin(),a.end());
cout<<a<<endl;
}
else{
cout<<a<<endl;
}
return 0;
}
G String Cards
思路:还是要写cmp函数,但要注意避免(2 2 ba b)这种情况了 单纯的写 return s1<s2; 会返回bba而不是bab, 应该组合起来判断 return s1+s2<s2+s1; 排序之后按倒序进行dp,最后输出dp[1][k]即可
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k,t;
string srr[55];
string dp[55][55];
bool cmp(string s1,string s2){
return s1+s2<s2+s1;
}
void solve(){
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>srr[i];
sort(srr+1,srr+1+n,cmp);
for(int i=n;i>0;i--){
for(int j=1;j<=n-i+1;j++){
if(dp[i+1][j]!="") dp[i][j]=min(dp[i+1][j],srr[i]+dp[i+1][j-1]);
else dp[i][j]=srr[i]+dp[i+1][j-1];
}
}
cout<<dp[1][k]<<endl;
}
signed main(){
t=1;
while(t--){
solve();
}
return 0;
}