A*B-dp好题
P2841 A*B-dp好题
题意
给出一个数 \(A\) ,你需要给出一个最小的数 \(B\) ,使得 \(A×B\) 的结果只含有 \(0\) 和 \(1\) 。
思路
初见
很容易想到枚举结果 \(C\) 的最小值,看看是否满足 \(A×C=B\)。然后。。 \(wa\) 了两个点。。发现 \(long long\) 小了点,换成 \(\_\_int128\) 然后 \(T\) 了,就说蓝题没有这么简单(但已经有 \(80\) 分了)。
思考
由于要求的是最小值,试着贪心,发现:
- 得到的结果类似于二进制数,可以考虑一些二进制的优化。
- 我们要求满足其是 A 的倍数,这和因数,余数等有关。
发现
二进制优化都是加法,想从因数下手是没辄了。但是余数似乎很有说法。
我们似乎可以将每个 \(100...\) 对 A 取模的余数预处理出来,然后不断从小往大添加,直到满足条件为止。
但是。。。这么贪心好像忽略了不少东西???
完善
如果好不顾虑的贪心,会有 \(1+1=2\) 的情况,但是完全按照 01 串的生成,时间复杂度直接爆炸,我们手动搓一下样例,就会发现在正常扩展时,有很多余数相同的01串。
| 01 串 (十进制) | 模 6 结果 |
|---|---|
| 1 | 1 |
| 10 | 4 |
| 11 | 5 |
| 100 | 4 已出现 |
| 101 | 5 已出现 |
| 110 | 2 |
| 111 | 3 |
| 1000 | 4 已出现 |
| 1001 | 5 已出现 |
| 1010 | 2 已出现 |
| 1011 | 3 已出现 |
| 1100 | 2 已出现 |
| 1101 | 3 已出现 |
| 1110 | 0 |
| 1111 | 1 已出现 |
而由这些串拓展出的串一定比取模最短的拓展出来长,且拓展出来的模数一定会被更小的串覆盖。
数学点说就是:由于 \(r\) 相同,所以 \(r*10 + (0/1) \mod q\)相等。
所以我们只用记录和拓展不同模数下的最短串,就可以得到结果。
代码
在代码之前先说点细节:
- 我们只要对最短的串拓展一次,但是要注意先从小的串开始
- 由于扩展是对随机一个可能的串进行的,所以 bfs 是一个不错的选择
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn = 1e4+10;
constexpr int maxm = 1e2+10;
int dp[maxn]; // 存串的id
int ri[maxn]; // 串id对应的dp_id=余数
char s[maxn][maxm];// 存串,其实可以直接存值
int n,idx;
queue<int> q; // 待处理的串的id
void write(__int128 x)
{
if(x/10>0)
{
write(x/10);
}
putchar((x%10)^48);
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("cjdl.in","r",stdin);
freopen("cjdl.out","w",stdout);
#endif // ONLINE_JUDGE
scanf("%lld",&n);
dp[++idx]=1;
ri[1]=1%n;
s[1][1]='1';
q.emplace(1);
int ans_id;
while(!q.empty())
{
int uid=q.front(); q.pop();
if(ri[uid]==0)
{
ans_id=uid;
break;
}
int r=ri[uid]*10%n;
if(!dp[r])
{
++idx;
int i=1;
for(;s[uid][i];++i)
{
s[idx][i]=s[uid][i];
}
s[idx][i]='0';
ri[idx]=r;
dp[r]=idx;
q.emplace(idx);
}
++r;
r%=n;// 记得取模
if(!dp[r])
{
++idx;
int i=1;
for(;s[uid][i];++i)
{
s[idx][i]=s[uid][i];
}
s[idx][i]='1';
ri[idx]=r;
dp[r]=idx;
q.emplace(idx);
}
}
__int128 x=0;
__int128 ans=0;
for(int i=1;s[ans_id][i];++i)
{
x=x*10+(s[ans_id][i]^48);
}
ans=x/n;
write(ans);
putchar(' ');
write(x);
return 0;
}

浙公网安备 33010602011771号