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;
}

UVA 1341 - Different Digits(数论),布布扣,bubuko.com

时间: 2024-08-08 05:35:13

UVA 1341 - Different Digits(数论)的相关文章

uva 1341 - Different Digits(数论+bfs)

题目链接:uva 1341 - Different Digits 题目大意:给定一个数字n,要求求一个数字m,m可以整除n,并且尽量组成的数字种类(0~9)尽量少,在种类相同的情况下数值尽量小. 解题思路:可以证明两种数字肯定可以组成m,假设有数字k,一种数字可以有k,kk,kkk,kkkk,-整除n剩的数一定在0~n-1之间,所以肯定存在两个由k数字组成的数字同模,那么这两个数相减所得到的数即使kkk00000,两种数字.于是肯定了范围,枚举数字,然后用bfs获取答案,维护最小值即可. #in

uva 10560 - Minimum Weight(数论)

题目连接:uva 10560 - Minimum Weight 题目大意:给出n,问说至少需要多少个不同重量的砝码才能称量1~n德重量,给出所选的砝码重量,并且给出k,表示有k个重量需要用上述所选的砝码测量. 解题思路:重量为1的砝码肯定要选,它可以表示到1的重量,那么下一个砝码的重量肯定选择3(2?1+1),这样1,3分别可以用一个砝码表示,而2,4分别为3-1和3+1,这样1~4的重量也都可以表示.于是有公式ai=si?1?2+1. #include <cstdio> #include &

uva 11105 - Semi-prime H-numbers(数论)

题目链接:uva 11105 - Semi-prime H-numbers 题目大意:H-number为4?k+1(k为非负数),H-composites为因子中含有H-number(不包括自己本身)的数,反之久是H-prime,给定n,求有多少H-composites. 解题思路:首先用筛选法求出范围内的H-prime,然后枚举两个判断乘积是否在范围内. #include <cstdio> #include <cstring> const int maxn = 1e6+5; ty

UVA 11754 - Code Feat(数论)

UVA 11754 - Code Feat 题目链接 题意:给定一个c个x, y1,y2,y3..yk形式,前s小的答案满足s % x在集合y1, y2, y3 ... yk中 思路:LRJ大白例题,分两种情况讨论 1.所有x之积较小时候,暴力枚举每个集合选哪个y,然后中国剩余定理求解 2.所有x之积较大时候,选定一个k/x尽可能小的序列,枚举x * t + y (t = 1, 2, 3...)去暴力求解. 代码: #include <stdio.h> #include <string.

UVA 718 - Skyscraper Floors(数论)

UVA 718 - Skyscraper Floors 题目链接 题意:在一个f层高的楼上,有e个电梯,每个电梯有x,y表示y + k * x层都可以到,现在要问从a层能否到达b层(中间怎么换乘电梯不限制) 思路:对于两个电梯间能不能换乘,只要满足y[i] + xx x[i] == y[j] + yy y[j].然后移项一下,就可以用拓展欧几里得求解,进而求出x,y的通解,然后利用通解范围x' >= 0, y' >= 0, x[i] x' + y[i] <= f, x[j] y' + y

UVA 10692 - Huge Mods(数论)

UVA 10692 - Huge Mods 题目链接 题意:求a0a1a2...mod m 思路:直接算肯定不行,利用欧拉定理ab=a(b mod phi(m) + phi(m))(b>=phi(m)),对指数进行降值处理,然后就可以利用快速幂去计算了,计算过程利用递归求解. 代码: #include <stdio.h> #include <string.h> const int N = 1005; int phi[N * 10], vis[N * 10], m, n, a[

uva 718 - Skyscraper Floors(数论+bfs)

题目链接:uva 718 - Skyscraper Floors 题目大意:一栋大楼,有F层楼,E个电梯,现在要从A层到B层,问是否可行,每个电梯给出Xi和Yi,代表这个电梯可以到达的层数Yi+k?Xi(k≥0) 解题思路:建图,以A,B以及电梯为节点建图,将可以到达A,B这两层的电梯与这两点建边,在将两两电梯可以达到同一层的建边,判断方法为:Yi+aXi=Yj+bXj,移项得:aXi+bXj=Yj?Yi,即是一个线性方程,用拓展欧几里得算法求出通解的形式,判断是否存在通解在0~F之间即可. #

UVA 10623 - Thinking Backward(数论)

UVA 10623 - Thinking Backward 题目链接 题意:给定一个数量,求用圆,椭圆,三角形分割平面,分割出该数量,输出所有情况 思路:有公式2 + 2m(m-1) + n(n-1) + 4mn + 3p(p-1) + 6mp + 6np 由于m和p都是[0,100],所以可以枚举m和p,去求出n,然后判断合不合适 代码: #include <stdio.h> #include <string.h> #include <math.h> #include

uva 11728 - Alternate Task(数论)

题目链接:uva 11728 - Alternate Task 题目大意:给出S,求N,要求N所有的因子和为S. 解题思路:枚举因子i,所有整除i的数和加上i. #include <cstdio> #include <cstring> const int N = 1005; int n, c[N], v[N]; void init () { memset(c, 0, sizeof(c)); memset(v, -1, sizeof(v)); for (int i = 1; i &l