列表

详情


NC15364. 小欧的烦恼

描述

小欧在上代数课的时候,老师向大家提出了一个问题,不定方程 ax+by=c 的整数解存在的充要条件是什么。
聪明的小欧立即举手给出了老师一个完美的回答,放学后,老师叫住小欧给了他一个思考题。
给出正整数 a 和 b 的值以及两个序列 S 和 V, 求出最小代价的正整数 c 使得不定方程 ax+by=c 有解,且 c 必须满足以下条件:
1. 组成 c 的数字必须是序列 S 内的。
2. 每使用序列 S 内的一个数字 Si 就会消耗掉代价 Vi
3. 序列 S 内的数字使用次数不限。
4. c 的首位为 u, c的末位为 v。(u,v 也是序列 S 内的) 
如果有多个代价一样小的答案,只需要 c 的字典序最小的那一个。

输入描述

第一行三个个整数 a,b,n (1 <= a, b <= 100000,  2 <= n <= 10) 
第二行 n 个整数 Si (0 <= Si <= 9) 
第三行 n 个整数 Vi (1 <= Vi <= 1000) 
最后一行两个整数 u,v(1 <= u <= 9,  0 <= v <= 9, u != v) 

输出描述

输出一行表示满足条件的 c 。
如果有多个输出字典序最小的。
如果不存在输出 -1 。

示例1

输入:

10 15 2
2 0
1 1
2 0

输出:

20

示例2

输入:

17 17 4
0 1 2 7
1 1 1 1000
1 0

输出:

1020

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 59ms, 内存消耗: 1892K, 提交时间: 2018-03-24 07:44:54

#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define M 15
int S[M],V[M],dis[N],Pre[N],cha[N];
bool mark[N];
queue<int>Q;
void output(int x){
	if (!~x) return;
	output(Pre[x]);
	printf("%d",cha[x]);
}
int main(){
	int a,b,n,i,u,v;
	cin>>a>>b>>n;
	int g=__gcd(a,b);
	for (i=1;i<=n;i++) cin>>S[i];
	for (i=1;i<=n;i++) cin>>V[S[i]];
	cin>>u>>v;
	memset(dis,63,sizeof(dis));
	dis[u%g]=0;
	Pre[u%g]=-1;
	cha[u%g]=u;
	Q.push(u%g);
	int Ans=-1;
	while (!Q.empty()){
		int x=Q.front();Q.pop();
		mark[x]=0;
		if ((x*10+v)%g==0 && !~Ans) Ans=x;
		for (i=0;i<=9;i++){
			if (!V[i]) continue;
			int to=(x*10+i)%g;
			if (dis[to]>dis[x]+V[i]){
				dis[to]=dis[x]+V[i];
				Pre[to]=x;
				cha[to]=i;
				if (!mark[to]){
					mark[to]=1;
					Q.push(to);
				}
			}
		}
	}
	if (Ans==-1){
		printf("-1\n");
	}else{
		output(Ans);
		printf("%d\n",v);
	}
	return 0;
}

上一题