A:
直接暴力枚举
const int N=1111122;
const int M=200005;
int ok(int x) {
if(x%10==3)return 1;
if(x%3==0)return 1;
return 0;
}
int is(int n) {
int x = 0;
while(n) {
x ++;
if(!ok(x))n --;
}
return x;
}
int main() {
int T,i,j,n,m;
cin >> T;
while(T--) {
cin >> n;
cout << is(n) << endl;
}
return 0;
}
B:
分类讨论即可
const int N=1111122;
const int M=200005;
int main() {
ll T,i,j,n,m,a,b,c;
cin >> T;
while(T--) {
cin >> a >> b >> c;
ll M = max(a,b);
ll x = abs(a - b);
if(M > x * 2) {
cout << -1 << endl;
continue;
}
if(c > x * 2)cout << -1 << endl;
else {
if(c <= x)cout << c + x << endl;
else cout << (c + x) % (x * 2) << endl;
}
}
}
C:
先找位于的列数,发现规律1 2 5 10…,然后找位于的行数,暴力即可
const int N=1111122;
const int M=200005;
void solve(ll n) {
ll x = 1 , i , sum = 0;
for(i=1;i;i) {
x ++;
sum += i;
if(sum >= n)break;
i += 2;
}
x --;
sum -= i;
int y = n - sum;
if(y <= x) {
cout << y << ' ' << x << endl;
}
else {
y -= x;
cout << x << ' ' << x - y << endl;
}
}
int main() {
ll T,i,j,n,m;
cin >> T;
while(T--) {
cin >> n;
solve(n);
}
}
D:
枚举从2的0次幂枚举到63次幂(因为可能后面某个数字的贡献更小),然后按顺序找最长的公共前缀,注意一定要按顺序(刚开始写了个最长公共子序列,这样是不对的,比如1045 和1024,公共长应该是2而不是3),答案就是需要加末尾的和需要删的之和
#define inf 0x3f3f3f3f
const int N=1111122;
const int M=200005;
int f[20][20],s1[20],s2[20];
ll a[1000];
int o,u;
void init() {
ll x = 1;
for(int i = 0 ; i <= 63 ; i ++) {
a[i] = x;
x *= 2;
}
}
int lcs() {
int x = o , i;
for(i=u;i>=1;) {
if(s1[x] == s2[i]) {
i --;
x --;
}
else x --;
if(x < 1)break;
}
return u - i;
}
int check(ll n,int c) {
ll x = a[c];
ll y = n;
o = 0 , u = 0;
while(y > 0) {
s1[++o] = y % 10;
y /= 10;
}
while(x > 0) {
s2[++u] = x % 10;
x /= 10;
}
int res = lcs();
return o - res + u - res;
}
int main() {
ll T,i,j,n,m;
cin >> T;
init();
while(T--) {
cin >> n;
int Min = inf;
for(i = 0 ; i <= 63 ; i ++) {
Min = min(Min , check(n , i));
}
cout << Min << endl;
}
}
E:
我们很容易得到在原字符串中每种字符的数量,由此从后往前进行枚举,得到一个字符串,然后进行check()该字符串,看他按照题目的描述得到的最终字符串和给的S是否一样
char s[N];
int flag,Mi,o,u,n;
int num[M],v[M],a[M],v2[M],s1[N],s2[N];
void ACM(int x,int y) {
int ans = num[a[y]];
for(int i = x ; i >= 0 ; i --) {
Mi = min(Mi , i);
if(s[i] == a[y])ans --;
if(ans == 0)return ;
}
if(ans)flag = 1;
}
void check() {
int len = u;
for(int i = o ; i >= 1 ; i --) {
v2[a[i]] = 1;
for(int j = 0 ; j < len ; j ++) {
if(!v2[s2[j]])s1[u ++] = s2[j];
}
}
if(u != n)flag = 1;
for(int i = 0 ; i < u ; i ++) {
if(s1[i] != s[i])flag = 1;
}
if(flag) {
cout << -1 << endl;
}
else {
for(int i = 0 ; i <= Mi ; i ++)printf("%c",s1[i] + 'a');
cout << ' ';
for(int i = o ; i >= 1 ; i--)printf("%c",a[i] + 'a');
cout << endl;
}
}
void solve() {
set<char> st;
int ans = 0,flag = 0;
n = strlen(s);
for(int i = n - 1 ; i >= 0 ; i --) {
s[i] -= 'a';
if(!v[s[i]])a[++ o] = s[i],v[s[i]] = 1;
num[s[i]] ++;
}
for(int i = 1 ; i <= o ; i ++) {
if(num[a[i]] % (o - i + 1))flag = 1;
num[a[i]] = num[a[i]] / (o - i + 1);
}
Mi = n - 1;
int x;
for(int i = 1 ; i < o ; i ++) {
x = Mi;
for(int j = 1 ; j <= i ; j ++) {
ACM(x , j);
}
Mi --;
}
for(int i = 0 ; i <= Mi ; i ++) {
num[s[i]] --;
}
for(int i = 0 ; i < 26 ; i ++){
if(num[i] != 0)flag = 1;
}
if(flag)cout << -1 << endl;
else {
for(int i = 0 ; i <= Mi ; i ++)
s1[u ++] = s[i] , s2[i] = s[i];
check();
}
}
int main() {
int T;
cin >> T;
while(T --) {
memset(v , 0 , sizeof v);
memset(v2 , 0 , sizeof v2);
memset(num , 0 , sizeof num);
flag = 0;o = 0,u = 0;
cin >> s;
solve();
}
return 0;
}
F1
赛中一直在分类讨论,越讨论情况越多…;赛后看别人用的二进制枚举,因为只可能包含两种数字,那么就枚举0~9种的任意两个数字,然后塞到set里,用st.lower_bound(),即可,注意不能直接用泛化函数lower_bound(),会直接超时
const int N = 1010;
const int M = 20010;
set<ll> st1,st2;
void init() {
for(int i = 1 ; i <= 9 ; i ++) {
ll ans = 0;
for(int j = 1 ; j <= 10 ; j ++) {
ans = ans * 10 + i;
st1.insert(ans);st2.insert(ans);
}
}
for(int i = 0 ; i <= 9 ; i ++) {
for(int j = i + 1 ; j <= 9 ; j ++) {
for(int k = 1 ; k < (1 << 10) ; k ++) {
ll ans = 0;
for(int g = 0 ; g <= 10 ; g ++) {
if(k & (1 << g))ans = ans * 10 + i;
else ans = ans * 10 + j;
st2.insert(ans);
}
}
}
}
}
int main() {
int T;cin >> T;
init();
while(T --) {
ll n,k;
cin >> n >> k;
if(k == 1)cout << *st1.lower_bound(n) << endl;
else cout << *st2.lower_bound(n) << endl;
}
return 0;
}
F2
对于一个数,如果第q位是第k+1种数字,那么假如第q位不是9,那么直接s[q]++,然后后面全部置为0即可,如果第q位是就,那么就往前找第一个不是9的,s[q]++;当然,一步得到的可能不是满足条件的,然后我们继续进行上述操作,直到满足条件
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define IO ios::sync_with_stdio(false)
#define bug cout << "-----\n"
typedef long long ll;
int Mod = 1000000007;
const int N = 500010;
const int M = 50;
char s[M];
int k;
set<char> st;
void solve() {
st.clear();
int n = strlen(s);
while(1) {
st.clear();//注意清st,否则超时
for(int i = 0 ; i < n ; i ++)
st.insert(s[i]);
if(st.size() <= k)
break;
st.clear();
int idx = 0;
while(st.size() <= k) {
st.insert(s[idx ++]);
}
while(s[--idx] == '9');
++s[idx];
for(int i = idx + 1 ; i < n ; i ++)s[i] = '0';
}
cout << s << '\n';
}
int main() {
IO;
int T;
cin >> T;
while(T --) {
cin >> s >> k;
solve();
}
return 0;
}