AcWing第93场周赛
整除数
给定两个整数 $ n,k $,请你找到大于 $ n $ 且能被 $ k $ 整除的最小整数 $ x $。
输入格式
共一行,包含两个整数 $ n,k $。
输出格式
输出大于 $ n $ 且能被 $ k $ 整除的最小整数 $ x $。
数据范围
前 $ 4 $ 个测试点满足 $ 1 \le n,k \le 100 $。
所有测试点满足 $ 1 \le n,k \le 10^9 $。
输入样例1:
5 3
输出样例1:
6
输入样例2:
25 13
输出样例2:
26
输入样例3:
26 13
输出样例3:
39
题目分析
对于任意的\(n\)和\(k\),都有\(n=q*k+r\),其中q是商,r是余数。$ 0 \le r < k$ 。
因此,分两种情况讨论即可。
- \(r=0\)。则此时余数为0,代表n被k整除。\(x=(q+1)*k\)
- \(r \le 0\)。则此时n不能被k整除,余数\(r\)一定严格小于k,则此时\(x=(q+1)*k\)
综上,\(x=(n/k+1)*k\)
#include <bits/stdc++.h>
using namespace std;
int n,k;
int main()
{
cin>>n>>k;
cout<<(n/k+1)*k<<endl;
return 0;
}
数字替换
给定两个整数 n,x。
你可以对 x 进行任意次以下操作:
- 选择 x 的一位数字 y,将 x 替换为 x×y。
请你计算通过使用上述操作,将 x 变为一个 n 位数字(不含前导 0),所需要的最少操作次数。
例如,当 n=3,x=2 时,对 2 进行如下 4 次操作,即可使其变为 3 位数字:
- 将 2 替换为 2×2=4。
- 将 4 替换为 4×4=16。
- 将 16 替换为 16×6=96。
- 将 96 替换为 96×9=864。
输入格式
共一行,包含两个整数 n,x。
输出格式
一个整数,表示将 x 变为一个 n 位数字,所需要的最少操作次数。
如果无解,则输出 -1。
数据范围
所有测试点满足 2≤n≤19,1≤x<10n−1。
输入样例1:
2 1
输出样例1:
-1
输入样例2:
3 2
输出样例2:
4
输入样例3:
13 42
输出样例3:
12
题目分析
题目类似《小猫爬山》,要再去复习一下提高课的dfs和搜索剪枝了
-
倒序搜索 搜索顺序优化,快速得到一个解,而不是快速得到最优解
-
之前的方案比现在的这种方案小,则可以现在直接退出。
-
预判一下:如果之前的方案是k步,当前这种方案已经用了x步,发现离目的还需要n-x步
即若当前的步数+相差的位数>=最优解,则可以直接退出了。
/*
题目类似《小猫爬山》,要再去复习一下提高课的dfs和搜索剪枝了
1. 倒序搜索 搜索顺序优化,快速得到一个解,而不是快速得到最优解
2. 之前的方案比现在的这种方案小,则可以现在直接退出。
3. 预判一下:如果之前的方案是k步,当前这种方案已经用了x步,发现离目的还需要n-x步
即若当前的步数+相差的位数>=最优解,则可以直接退出了。
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int ans = 0x3f3f3f3f;
int n;
void dfs(ll x,int res)
{
int cnt = 0; // 记录当前x的位数
bool st[10]={0}; // 表示当前x要变化下一步的话,能用哪些数字
for (ll i=x;i;i/=10) // 求解x的位数和对于x来说哪些数字能用
{
cnt++;
st[i%10]=true;
}
// 剪枝1:预判一下这种方案还有没有希望是答案
if (res+n-cnt>=ans) return;
if (cnt==n)
{
// 剪枝2:最优性剪枝
if (res<ans)
ans=res;
return;
}
// 扩展求解答案,即从9~2每一个符合条件的数字都试
for (int i=9;i>=2;i--)
{
if (st[i])
dfs(x*i,res+1);
}
}
int main()
{
ll x;
cin>>n>>x;
dfs(x,0);
if (ans==0x3f3f3f3f) ans=-1;
cout<<ans<<endl;
return 0;
}
异或值
给定一个长度为 $ n $ 的整数序列 $ a_1,a_2,…,a_n $。
请你找到一个非负整数 $ X $,使得 $ \max \limits_{1 \le i \le n} { a_i \oplus X } $ 的值尽可能小,其中 $ \oplus $ 表示按位异或。
输出 $ \max \limits_{1 \le i \le n} { a_i \oplus X } $ 的最小可能值。
输入格式
第一行包含整数 $ n $。
第二行包含 $ n $ 个整数 $ a_1,a_2,…,a_n $。
输出格式
一个整数,表示 $ \max \limits_{1 \le i \le n} { a_i \oplus X } $ 的最小可能值。
数据范围
前 $ 3 $ 个测试点满足 $ 1 \le n \le 3 $。
所有测试点满足 $ 1 \le n \le 10^5 \(,\) 0 \le a_i \le 2^{30}-1 $。
输入样例1:
3
1 2 3
输出样例1:
2
输入样例2:
2
1 5
输出样例2:
4
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3000010, INF = 2e9;
int n;
int tr[N][2], idx;
void insert(int x)
{
int p = 0;
for (int i = 29; i >= 0; i -- )
{
int u = x >> i & 1;
if (!tr[p][u]) tr[p][u] = ++ idx;
p = tr[p][u];
}
}
int dfs(int u, int d)
{
if (d == -1) return 0;
int f[2];
for (int i = 0; i < 2; i ++ )
{
int p = tr[u][i];
if (p) f[i] = dfs(p, d - 1);
else f[i] = -1;
}
int res = INF;
for (int i = 0; i < 2; i ++ )
{
int t = 0;
for (int j = 0; j < 2; j ++ )
if (f[j] != -1)
t = max(t, f[j] + ((i ^ j) << d));
res = min(res, t);
}
return res;
}
int main()
{
scanf("%d", &n);
while (n -- )
{
int x;
scanf("%d", &x);
insert(x);
}
printf("%d\n", dfs(0, 29));
return 0;
}

浙公网安备 33010602011771号