哈理工新生赛 T-小乐乐与二段数

题目描述
二段数是这样的正整数:恰好包含两种不同的十进制数字s和t,s不是0,并且s的所有出现均排列在所有的t的前面。例如,44444411是二段数(s是4,t是1),41、10000000和5555556也是。但4444114和44444都不是二段数。
给你一个任意的正整数n,你能求出比n大并且是n的倍数的最小二段数吗
输入描述:
多组输入,每组输入包含一个正整数n (1 ≤ n ≤ 99999)
输出描述:
对于每组测试用例,输出正整数n,后面紧跟“: ”,输出答案并换行,即比n大且是n的倍数的最小二段数。

**输入**
1
2019
0
**输出**
1: 10
2019: 9999999993

AC代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=10010;   //表示最大的位数长度
int a[maxn],b[maxn];
//例如999999993  就可以看做个8个9   1个3
//对应四个变量 我们存储一下  m个s和n个t组成
//二段数m,s,n,t除以N的余数等于(a[m]*b[n]*s+a[n]*t) mod N。
int m,total,s,t,aptotal,apm,aps,apt,k;//我们让total来存储这个数的位数 这样n就可以用total-m来赋值
int n; //注意这里的n是我们要输入的值
bool ck()
{
	int p,r;
	//我们让p储存s,r存储t
	if (total > 5)
		return 1;
	p=s;
	r=t;
	for(int q=0;q<m;q++)
	{
		p=p*10+s;
	}
	//我们需要将p扩10的total-m次方
	for (int q = 0; q < total-m; q++)
		p = p * 10;
	for (int q = 1; q < total-m; q++)
		r = r * 10 + t;
	return p+r>n;
}
int main()
{
	while(scanf("%d",&n),n)
	{
		printf("%d: ", n);
		if (n == 1) {
			puts("10");
			continue;
		}
		//下面我们来介绍a数组和b数组含义
		//a[1]=1 a[i+1]=(a[i]*10+1)%n; i = 1,2,3,… a[i]就是连续i个1除以N的余数
		//b[0]=1 b[i+1]=(b[i]*10)%n; i = 0,1,2,3,… b[i]就是10的i次方除以N的余数。
		a[0]=1;
		b[0]=1;
		//下面我们就要初始化a,b数组了
		for(int i=1;i<9999;i++)
			a[i]=(a[i-1]*10+1)%n;
		for (int i = 1; i < 999; i++)
			b[i] = b[i - 1] * 10 % n;
		//我们让total来存储这个数的位数 这样n就可以用total-m来赋值
		//接下来接下来只要枚举m,s,n,t就可以了。按照(m+n)的值从小到大枚举,(m+n)确定后枚举m,则n可以直接计算出来,不需要枚举。m和n确定之后枚举s和t。一旦找到解,后面的(m+n)值就不需要继续枚举下去了。
		for (total = 1, aps = 0; total < 9999; total++) {
			k = 0;
			if ((n % 10 == 0 || n % 25 == 0) && total> 11)
				k = total - 11;
			for (m = k; m < total; m++)
				for (s = 1; s < 10; s++)
					for (t = 0; t < (n % 10 ? 10 : 1); t++)
						if(t!=s&&(((long long)a[m]) * b[total - m] * s + a[total - m - 1] * t) % n == 0 && ck()&&
							(!aps||s<aps))
						{
							aptotal=total;
							apm=m;
							aps=s;
							apt=t;
						}
			if (aps)
				break;
		}
		for (int x = 0; x < apm + 1; x++)
			printf("%d", aps);
		for (int x = 0; x < aptotal - apm; x++)
			printf("%d", apt);
		printf("\n");
	}
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值