A.Dislike of Threes
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=2e5+10;
int f[N];
int cnt;
int main()
{
for(int i=1;;i++){
if(i%3!=0&&i%10!=3) f[++cnt]=i;
if(cnt>=1000) break;
}
int t;
cin>>t;
while(t--){
int k;
cin>>k;
cout<<f[k]<<endl;
}
return 0;
}
B.Who's Opposite?
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void solve()
{
int a,b,c;
cin>>a>>b>>c;
if(a>b) swap(a,b);
int sum=2+(b-a-1)*2;
if(c>sum){
cout<<-1<<endl;
return;
}
if(c<=sum/2) c+=(b-a);
else c-=(b-a);
if(a>sum||b>sum){
cout<<-1<<endl;
return;
}
if(c==a||c==b){
cout<<-1<<endl;
return;
}
if(c<1||c>sum){
cout<<-1<<endl;
return;
}
cout<<c<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
C.Infinity Table
每一行的第一个都是2的次幂,通过二分来找到是哪一行
注意二分的范围,如果开太大,平方超出int范围,会变成负数,导致错误
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int sqr(int x){
return x*x;
}
void solve()
{
int k;
cin>>k;
int l=1,r=4e4;
while(l<r){
int mid=(l+r)/2;
if(sqr(mid)>=k) r=mid;
else l=mid+1;
}
int x,y;
int diff=sqr(l)-k;
if(diff<=l-1) {
x=l;
y=diff+1;
}
else{
x=l-(diff-(l-1));
y=l;
}
cout<<x<<" "<<y<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
D.Make a Power of Two
先打表,预处理2的次幂,以字符串的形式存储,存储尽可能多的2的次幂(因为还有前导0)
数字n也以字符串的形式输入进来,记为字符串ss,然后将字符串与打好表的所有2的次幂进行比较,
利用双指针,必须从左往右按顺序依次匹配,也就是说对于每一个2的次幂字符串,如果前一位没有被匹配,那么就不去匹配后一位,因为只能在最右边加数,前一位没有匹配到,我们是不能通过删除和在右边添加元素来使得这个数出现的
然后如果某一个2的次幂每一位都被匹配的话,就只要删除多余的位数
否则,除了要删除多余的位数,还要在右边添加没有匹配到的位数
用res记录答案,对于变成每一个2次幂所需的操作次数,都取最小
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
const int N=110;
string s[N];
//打表
void init()
{
for(int i=0;i<61;i++){
int x=1ll<<i;
s[i]=to_string(x);
}
}
void solve()
{
string ss;
cin>>ss;
int res=2e9;
for(int i=0;i<61;i++){
int match=0;
int p=0,q=0;
while(ss[q]){
if(ss[q]==s[i][p]){
p++;
match++;
}
q++;
}
int len1=s[i].size(),len2=ss.size();
if(match==len1) res=min(res,len2-match);
else res=min(res,len2-match+len1-match);
}
cout<<res<<endl;
}
signed main()
{
init();
int t;
cin>>t;
while(t--)
solve();
return 0;
}
或者在双指针匹配的同时,如果不匹配就执行删除操作(即操作数+1),然后最后s[i]中没有匹配的都加到ss的右边
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
const int N=110;
string s[N];
void init()
{
for(int i=0;i<61;i++){
int x=1ll<<i;
s[i]=to_string(x);
}
}
void solve()
{
init();
string ss;
cin>>ss;
int res=2e9;
for(int i=0;i<61;i++){
int cnt=0;
int match=0;
int p=0,q=0;
while(ss[p]){
if(ss[p]==s[i][q]){
q++;
match++;
}
else cnt++;
p++;
}
int len1=ss.size(),len2=s[i].size();
res=min(res,cnt+len2-match);
}
cout<<res<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
E.Polycarp and String Transformation
先根据变换后的字符串t得到删除的字符及其顺序,因为字符越是在后面则越晚被删除
然后因为原字符串s第一次加到了字符串t中,所以只需确定其长度即可通过遍历得到
原字符串s的长度为字符串t中第一次删除的字符个数+第二次删除的字符个数除以2+...
然后遍历得到字符串s
最后验证字符串s按题目操作之后得到的字符串是否和t相等,如果相等则正确,否则输出-1
注意,vector.erase()中要写迭代器,即地址,不能写值
for(auto v:s) 得到的v是值,不能直接erase(值)
可以用vector删除所有与指定值相等的元素
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<vector>
using namespace std;
void solve()
{
string ss;
cin>>ss;
set<char>se;
string ans;
map<char,int>mp;
vector<char>s;
for(int i=ss.size()-1;i>=0;i--){
if(!se.count(ss[i])){
se.insert(ss[i]);
ans=ss[i]+ans;
}
mp[ss[i]]++;
}
int len=0;
for(int i=0;i<ans.size();i++) {
mp[ans[i]]/=(i+1);
len+=mp[ans[i]];
}
for(int i=0;i<len;i++) s.push_back(ss[i]);
//验证
string tt="";
for(int i=0;i<ans.size();i++){
for(auto v:s) tt+=v;
s.erase(remove(s.begin(),s.end(),ans[i]),s.end());
}
if(tt==ss){
for(int i=0;i<len;i++) cout<<ss[i];
cout<<" ";
cout<<ans<<endl;
}
else cout<<-1<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
F1.F2.
Nearest Beautiful Number (easy version)
Nearest Beautiful Number (hard version)
参考zhbbbb!
判断当前n不同数字个数是不是小于等于k,如果小于等于k,则直接输出
找到第一个大于k的不同数,这是关键,每次都是找第一个大于k的不同数
使得这位数+1,后面全置为0,原因是该位已经是第k+1位不同的数了,并且我们要找的数需要大于等于n,所以只能将其变大,但又不能一下子变太大,因为要找最小的大于等于n的,故加1,然后再判断当前n不同数字的个数是否小于等于k,如此反复
注意,如果找到的第k+1个不同的数是9,则需要进位,那么只需要往前移动,直到找到不是9的位,对其+1,然后后面全部置为0
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<vector>
using namespace std;
void solve()
{
string ss;
cin>>ss;
int k;
cin>>k;
while(1){
set<char>s;
for(int i=0;i<ss.size();i++) s.insert(ss[i]);
if(s.size()<=k){
cout<<ss<<endl;
return;
}
s.clear();
int pos=0;
while(1){
s.insert(ss[pos]);//将字符从左到右一个一个的放入set中
if(s.size()>k){
while(ss[pos]=='9') pos--;
ss[pos]++;
for(int i=pos+1;i<ss.size();i++) ss[i]='0';
break;
}
pos++;
}
}
}
signed main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}