文章目录
D. Make a Power of Two
题意:
给一个数
n
n
n,可以删除某一位或在后面添加任意一个数,求把
n
n
n变为二的幂次最少需要多少步
思路:枚举+双指针
暴力枚举
n
n
n到
x
=
2
0
∼
2
62
x=2^0\sim 2^{62}
x=20∼262需要几步,统计
n
n
n的子序列能最多匹配
x
x
x的前缀的长度
l
e
n
len
len
步数为
∣
n
∣
−
l
e
n
+
∣
x
∣
−
l
e
n
|n|-len+|x|-len
∣n∣−len+∣x∣−len,
∣
n
∣
−
l
e
n
|n|-len
∣n∣−len表示要变成
x
x
x的前缀需要删掉几个数,
∣
x
∣
−
l
e
n
|x|-len
∣x∣−len表示要添加前缀后面的数
AC代码:
#include <string>
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i ++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define MST(a,x) memset(a,x,sizeof(a))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define ll long long
#define int ll
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ls u<<1
#define rs u<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
const int MAXN=100;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
string s[MAXN];
int get(string t,string s){
int i=0,j=0;
while(i<SZ(t)){
if(t[i]==s[j]) i++,j++;
else i++;
if(j==SZ(s)) break;
}
return SZ(t)+SZ(s)-2*j;
}
void solve(){
string t;
cin>>t;
int ans=2e9;
rep(i,0,62){
ans=min(ans,get(t,s[i]));
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int x=1;
s[0]="1";
rep(i,1,62){
x*=2;
s[i]=to_string(x);
}
int t;cin>>t;while(t--)
solve();
return 0;
}
E. Polycarp and String Transformation
题意:
有两个字符串
s
,
t
s,t
s,t和一个给定顺序
o
r
d
e
r
order
order,最初
t
=
s
t=s
t=s,然后每次把
s
s
s里所有的
o
r
d
e
r
i
order_i
orderi删除加到
t
t
t里去,现在给你
t
t
t,输出
s
s
s和
o
r
d
e
r
order
order
思路:模拟+思维
由于删除顺序,所以每个字符的最后的出现位置即为
o
r
d
e
r
order
order,
t
t
t中出现的字符数一定是
s
s
s出现次数的倍数,用
c
n
t
cnt
cnt表示每个字符出现的次数,
o
r
d
e
r
i
order_i
orderi对应字符在
s
s
s中的次数为
c
n
t
o
r
d
e
r
i
i
+
1
0
≤
i
<
∣
o
r
d
e
r
∣
\frac{cnt_{order_i}}{i+1}\space 0\le i< |order|
i+1cntorderi 0≤i<∣order∣,因此
s
s
s中的总字符数为
∑
i
=
0
∣
o
r
d
e
r
∣
−
1
c
n
t
o
r
d
e
r
i
i
+
1
\sum_{i=0}^{|order|-1} \frac{cnt_{order_i}}{i+1}
∑i=0∣order∣−1i+1cntorderi,再根据题意模拟是否等于
t
t
t,否则输出
−
1
-1
−1
AC代码:
#include <iostream>
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i ++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define MST(a,x) memset(a,x,sizeof(a))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define ll long long
#define int ll
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ls u<<1
#define rs u<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
const int MAXN=1;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
string t,order="";
map<char,int> vis,cnt;
bool check(string s){
string res;
rep(i,0,SZ(order)-1){
res+=s;
s.erase(remove(s.begin(),s.end(),order[i]),s.end());
}
return res==t;
}
void solve(){
cin>>t;
order="";
int n=SZ(t),len=0;
vis.clear();
cnt.clear();
per(i,n-1,0){
if(!vis[t[i]]){
order=t[i]+order;
vis[t[i]]=1;
}
cnt[t[i]]++;
}
int res=0;
rep(i,0,SZ(order)-1) res+=cnt[order[i]]/(i+1);
// cout<<res<<endl;
string s1="";
rep(i,0,res-1) s1+=t[i];
if(check(s1)){
cout<<s1<<" "<<order<<endl;
}else cout<<"-1\n";
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}
F2. Nearest Beautiful Number (hard version)
题意:
给定两个数
n
,
k
n,k
n,k,找到
≥
n
\ge n
≥n的最小的
x
x
x,
x
x
x中出现数的种类
≤
k
\le k
≤k
思路:枚举+贪心
如果
n
n
n符合条件,直接输出
n
n
n,如果
k
=
1
k=1
k=1,如果所有位全取第一个数合法则输出,否则把每一位加一,如果
k
>
1
k>1
k>1从后往前枚举
n
n
n的每一位,枚举这位到
9
9
9的所有情况,
c
n
t
cnt
cnt表示当前出现数的种数,如果
c
n
t
=
k
cnt=k
cnt=k,那么后面的位全取之前出现最小位,如果
c
n
t
<
k
cnt<k
cnt<k,后面的位可以全取
0
0
0
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define ll long long
#define int ll
#define pb push_back
#define mp make_pair
#define SZ(x) (int)(x.size())
#define ALL(x) (x).begin(),(x).end()
#define mst(a,x) memset(a,x,sizeof(a))
#define ls u<<1
#define rs u<<1|1
typedef vector<int> VI;
typedef pair<int,int> PII;
const int maxn=1e6+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
int getcnt(string s)
{
set<char> S;
for(auto c:s) S.insert(c);
return SZ(S);
}
void solve()
{
string n;
int k;
cin>>n>>k;
string res;
int num=stoi(n);
if(getcnt(n)<=k) cout<<n<<endl;
else
{
if(k==1)
{
rep(i,1,SZ(n)) res+=n[0];
if(stoi(res)>=num) cout<<res<<endl;
else
{
for(auto &c:res) c++;
cout<<res<<endl;
}
}
else
{
int cnt=0,res=2e9;
while(SZ(n))
{
while(n.back()<'9')
{
n.back()++;
string cur=n;
int p=getcnt(n);
if(p<=k)
{
char minv='9';
for(auto t:n) minv=min(minv,t);
rep(i,1,cnt)
{
if(p==k) cur+=minv;
else cur+='0';
}
res=min(res,stoi(cur)*1ll);
}
}
n.pop_back();
cnt++;
}
cout<<res<<endl;
}
}
}
signed main()
{
#ifdef LOCAL
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}