UVA 1341 - Different Digits(数论)

UVA 1341 - Different Digits

题目链接

题意:给定一个正整数n。求一个kn使得kn上用的数字最少。假设同样,则输出值最小的

思路:
首先利用鸽笼原理证明最多须要2个数字去组成
设一个数字k。组成k,kk,kkk,kkkk... %n之后余数必定在0 - (n - 1)之间,所以必定能选出两个余数相等的数字相减为0,这个数字就是由0和k组成的。

因此仅仅要考虑一个数字和两个数字的情况,去bfs。记忆化余数。由于余数反复必定形成周期了

代码:

#include <stdio.h>
#include <string.h>

const int INF = 0x3f3f3f3f;
const int N = 66666;
int n, num[2], vis[N], ans, save[N];
struct Queue {
    int mod, pre, num, len;
    Queue(){}
    Queue(int mod, int pre, int num, int len) {
	this->mod = mod;
	this->pre = pre;
	this->num = num;
	this->len = len;
    }
} q[N * 2];

void out(int now, int d) {
    if (now == -1) return;
    out(q[now].pre, d - 1);
    save[d] = q[now].num;
}

int judge(int now, int d) {
    if (now == -1) return 0;
    int tmp = judge(q[now].pre, d - 1);
    if (tmp != 0) return tmp;
    if (save[d] == q[now].num) return 0;
    else if (q[now].num < save[d]) return -1;
    else return 1;
}

void bfs() {
    int head = 0, tail = 0;
    if (num[0] != 0) {
	q[tail++] = Queue(num[0] % n, -1, num[0], 1);
	vis[num[0] % n] = 1;
    }
    if (num[1] != -1 && num[1] != 0) {
	q[tail++] = Queue(num[1] % n, -1, num[1], 1);
	vis[num[1] % n] = 1;
    }
    while (head < tail) {
	Queue now = q[head];
	if (now.len > ans) return;
	if (now.mod == 0) {
	    if (now.len <= ans) {
		if (now.len != ans || judge(head, ans - 1) < 0) {
		    ans = now.len;
		    out(head, ans - 1);
		}
	    }
	}
	Queue next;
	for (int i = 0; i < 2; i++) {
	    if (num[i] == -1) continue;
	    next = Queue((now.mod * 10 + num[i]) % n, head, num[i], now.len + 1);
	    if (vis[next.mod]) continue;
	    vis[next.mod] = 1;
	    q[tail++] = next;
	}
	head++;
    }
}

int main() {
    while (~scanf("%d", &n) && n) {
	ans = INF;
	for (int i = 1; i < 10; i++) {
	    num[0] = i; num[1] = -1;
	    memset(vis, 0, sizeof(vis));
	    bfs();
	}
	if (ans == INF) {
	    for (int i = 0; i < 10; i++) {
		for (int j = i + 1; j < 10; j++) {
		    num[0] = i; num[1] = j;
		    memset(vis, 0, sizeof(vis));
		    bfs();
		}
	    }
	}
	for (int i = 0; i < ans; i++)
	    printf("%d", save[i]);
	printf("\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值