T1
给出
f
(
x
)
=
i
n
t
(
r
e
v
e
r
s
e
(
x
)
)
f(x)=int(reverse(x))
f(x)=int(reverse(x)),例如
f
(
123
)
=
321
,
f
(
100
)
=
001
=
1
f(123)=321,f(100)=001=1
f(123)=321,f(100)=001=1。
再给出
g
(
x
)
=
x
f
(
f
(
x
)
)
g(x)=\frac{x}{f(f(x))}
g(x)=f(f(x))x,输入一个整数n。求
1
≤
x
≤
n
1\leq x\leq n
1≤x≤n,构成的
g
(
x
)
g(x)
g(x)集合中有几个元素。
1
≤
x
≤
1
0
100
1\leq x\leq10^{100}
1≤x≤10100
签到题,观察题目,发现例如123,189,这样结尾不带0的求出来之后
g
(
x
)
=
1
g(x)=1
g(x)=1。
例如
g
(
90
)
=
10
,
g
(
900
)
=
100
,
g
(
800
)
=
100
,
g
(
1000
)
=
1000
g(90)=10,g(900)=100,g(800)=100,g(1000)=1000
g(90)=10,g(900)=100,g(800)=100,g(1000)=1000,也就是多一位就可以多一个10的倍数。求一下输入的x的长度就行了。
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
#define rep(i, sta, en) for(int i=sta; i<=en; ++i)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op) putchar(op); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); if (op) putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 7;
void solve() {
char s[N];
scanf("%s", s);
int len = strlen(s);
print(len);
}
int main() {
int T = read(); while (T--)
solve();
return 0;
}
T2
沿着x轴正方向跳格子,第几个回合你的正向跳跃距离就是几。但是你的回合也可以选择后退一个格子。问跳到x=p点处最小的跳跃次数。
1
≤
p
≤
1
0
6
1\leq p\leq10^6
1≤p≤106
我们不难发现上面就是一个等差数列求和,例用求和公式,先计算一下如果恰好一次都不后退可以跳到目标点,直接输出等差数列的项数即可。如果我们只在第一次跳跃后退,那么我们最终答案就会变成 n ∗ ( n − 1 ) / 2 − 2 n*(n-1)/2-2 n∗(n−1)/2−2,因为之前+1,现在-1,对长度的影响是2。那么同理,如果我们只在第二次跳跃的时候回退,我们对长度的影响是3,在第n-1次跳跃的时候回退,对长度的影响就是n。那么如果我们上面不能直接通过等差数列跳到目标点,那么我们就可以使用n次等差数列跳跃去到第一个大于等于n的点,接下来我们如果刚好停在了x+1处,但是我最小的回退距离都是2,说明无法通过修改中间步骤进行调整,只能原地回退一步,但是如果我们停在大于x+1的地方,一定向前跳跃的时候选择一步进行回退,让终点刚好停在x处。
void solve() {
int n = read();
int ans = 1;
while (ans * (ans + 1) < 2 * n)
++ans;
if (ans * (ans + 1) / 2 == n + 1) ++ans;
print(ans);
}
T3
博弈题,给出双方体力x和y,由x体力的人先发球,每次发球消耗一点体力,对方可以选择也消耗一点体力将这个球打回去,这样x就不能得分。谁得分下一次球就是谁发,现在他们两个人都希望在自己得分最高为第一前提,其次在降低对方得分的情况下,双方的最高得分分别是几。
1
≤
x
,
y
≤
1
0
6
1\leq x,y\leq10^6
1≤x,y≤106
看到双方都要最大化自己的比分,那么做为后手的y,只能在x发完最后一球,没有体力的时候进行反击一定会最大化自己的得分,那么x的最大得分就是发球数-1了。
void solve() {
n = read(), m = read();
printf("%lld %lld\n", n - 1, m);
}
T4
给出长度为n的序列,以及起始的x。你可以选择一个元素
a
i
a_i
ai,如果保证了
a
i
>
x
a_i>x
ai>x,你就可以选择交换这两个元素,使用x填充进之前
a
i
a_i
ai的位置,并且把
a
i
a_i
ai看成新的x,进行下一次匹配。询问在最少的次数交换中使得序列变得非递减,这样的交换次数是几次。如果永远无法有序输出-1。
1
≤
n
,
x
≤
500
1\leq n,x\leq500
1≤n,x≤500
动态规划题目,我们使用
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]代表当前使用
j
j
j替换掉
a
i
a_i
ai的最少替换次数。那么接下来我们就可以找到递推的方程,首先第一次替换的时候,我们找出全部可以用初始的x替换的点更新成1,其余赋值无穷大。注意如果当前遍历的
a
i
>
a
i
+
1
a_i>a_{i+1}
ai>ai+1,说明不需要继续往后面找第一次替换了,因为这个地方如果不更新
a
i
a_i
ai,下一次我们只能把
a
i
+
1
a_{i+1}
ai+1变成一个更小的x,显然无法使得它变成有序的。
下面的递推式就是,使用双重的循环,枚举
i
i
i和
j
j
j了,保证
d
p
[
i
]
[
j
]
!
=
I
N
F
dp[i][j]!=INF
dp[i][j]!=INF前提,如果
i
i
i走到了n说明替换完成,或者使用
j
j
j替换
a
i
a_i
ai后,序列满足了要求,也可以更新一次答案。下面就是状态的转移了,我们使用
j
j
j替换
a
i
a_i
ai之后,枚举
k
k
k,尝试使用
a
i
a_i
ai替换
a
k
a_k
ak。也是要注意保证序列要有序的前提下。
const int N = 500 + 7;
ll n, m;
int dp[N][N], a[N];
void solve() {
n = read(), m = read();
rep(i, 1, n) a[i] = read();
if (is_sorted(a + 1, a + 1 + n)) { print(0); return; }
ms(dp, 0x3f);
rep(i, 1, n) {
if (a[i] > m and (i == 0 or a[i - 1] <= m))
dp[i][m] = 1;
if (i<n and a[i]>a[i + 1])
break;
}
int ans = INF;
rep(i, 1, n) {
rep(j, 0, 500) {
if (dp[i][j] == INF) continue;
if (i == n or (j <= a[i + 1] and is_sorted(a + i + 1, a + n + 1)))
ans = min(ans, dp[i][j]);
rep(k, i + 1, n) {
int pre = (k == i + 1 ? j : a[k - 1]); // a[i]已经被替换成j的前提下
if (a[i] >= pre and a[k] > a[i]) // 可以把a[i]换入a[k]
dp[k][a[i]] = min(dp[k][a[i]], dp[i][j] + 1);
if (a[k] < pre) break; // 出现了一个不合理的排序对
}
}
}
if (ans == INF) ans = -1;
print(ans);
}