[爆搜]Torchbearer

题目大意

给定一个正整数 \(n\) , 求最小的正整数 \(m\) 满足 \(n * m\) 的值的每位由 \(0, 1\)构成(十进制下)。

思路

本来看到 \(0,1\)串,想到的是用二进制搞。
但是发现自己这方面存在大锅,而且人也很菜。
于是转变了思考方向。
对于乘积的每一位都是由 \(0,1\) 构成,那么考虑模拟乘法。
因为乘法每次都是高一位的,所以每次考虑枚举 \(0\)\(9\) 作为所求的 \(m\) 这一位。
每次就取出最后一位,让最后一位和上一次除最后一位的剩余贡献的最后一位相加,所得的数经过整除十后应该是 \(0\)\(1\)
再想,当除最后一位剩余的数加上上一次除最后一位的剩余贡献的和也是一个 \(0,1\) 串时,那么这个 \(m\) 就是显然成立的。
再考虑如何优化。
显然,这个算法是从后往前模拟的,所以无法在模拟中直接判断大小。
考虑在每一位搜完这一层再搜下一层,这样当这一层有结果时,下面几层的解显然是劣与这一层的结果的(位数)。
还有考虑 \(m\) 不为 \(0\) 的情况。数据(这个数据真的水,999,9999,99999的情况都没有,这些的结果都是暴ull的。特别是99999,长度高达42位。。。)删除

Code

#include <bits/stdc++.h>
#define ll unsigned long long
#define INF 1844674407370955161
using namespace std;

ll a[10];
ll n, len, ans = INF, fir = 1;

void hhd (ll last, ll d, ll base)
{
	if (d > ans) return ;
	if (!d)
	{
		if (fir) fir = 0;
		else return ;
	}
	ll aut[15];
	for (int i = 0; i <= 9; ++ i)
	{
	//	printf ("last = %d   d = %d    i = %d    	result = %d\n", last, d, i, a[len] * i % 10 + last % 10);
		aut[i] = 0;
		ll kt = a[len] * i % 10 + last % 10;
		if (kt % 10 == 1 || kt % 10 == 0)
		{
			ll te = (n * i + last) / 10, tes, fl = 1, rt;
			tes = te;
			while (tes)
			{
				rt = tes % 10;
				if (rt != 1 && rt != 0) 
				{
					fl = 0;
					break;
				}
				tes /= 10;
			}
			//printf ("d = %d   te = %d   i = %d   last = %d    kt = %d    fl = %d\n", d, te, i, last, kt, fl);
			if (fl && d) 
			{
				ans = min (ans, d + i * base);
				return ;
			}
			else aut[i] = 1;
		}
	}
	for (int i = 0; i <= 9; ++ i)
	{
	//	printf ("last = %d   d = %d    i = %d    	result = %d\n", last, d, i, a[len] * i % 10 + last % 10);
		if (aut[i])
		{
			ll te = (n * i + last) / 10;
			hhd (te, d + i * base, base * 10);
		}
	}
}

int main ()
{
	scanf ("%d", &n);
	ll n_ts = n;
	while (n_ts)
	{
		a[++ len] = n_ts % 10;
		n_ts /= 10;
	}
	ll a_ts[10];
	for (int i = 1; i <= len; ++ i) a_ts[i] = a[i];
	for (int i = 1; i <= len; ++ i) a[i] = a_ts[len - i + 1];
	hhd (0, 0, 1);
	if (ans != INF) printf ("%lld", ans);
	else printf ("no solution");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值