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.h>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

const int N = 15;
const int M = 105;

int c, s, x[N], k[N], y[N][M], now;
set<int> value[N];
vector<long long> ans;
long long a[N];

void solve_enum() {
	for (int i = 0; i < c; i++) {
		if (c == now) continue;
		value[i].clear();
		for (int j = 0; j < k[i]; j++)
			value[i].insert(y[i][j]);
 	}
 	for (int t = 0; ; t++) {
 		for (int i = 0; i < k[now]; i++) {
 			long long n = (long long)x[now] * t + y[now][i];
 			if (n == 0) continue;
 			bool ok = true;
 			for (int i = 0; i < c; i++) {
 				if (i == now) continue;
 				if (!value[i].count(n % x[i])) {ok = false; break;}
    		}
    		if (ok) {printf("%lld\n", n); if (--s == 0) return;}
   		}
  	}
}

long long exgcd(long long a, long long b, long long &x, long long &y) {
	if (!b) {x = 1; y = 0; return a;}
	long long d = exgcd(b, a % b, y, x);
	y -= a / b * x;
 	return d;
}

long long china() {
	long long M = 1, ans = 0;
 	for (int i = 0; i < c; i++)
 		M *= x[i];
	for (int i = 0; i < c; i++) {
		long long w = M / x[i];
		long long xx, yy;
		exgcd(x[i], w, xx, yy);
		ans = (ans + w * yy * a[i]) % M;
 	}
 	return (ans + M) % M;
}

void dfs(int d) {
	if (d == c) {
		ans.push_back(china());
		return;
 	}
 	for (int i = 0; i < k[d]; i++) {
 		a[d] = y[d][i];
 		dfs(d + 1);
	}
}

void solve_china() {
	ans.clear();
	dfs(0);
	sort(ans.begin(), ans.end());
	long long M = 1;
	for (int i = 0; i < c; i++) M *= x[i];
	for (int i = 0; ; i++) {
		for (int j = 0; j < ans.size(); j++) {
			long long n = M * i + ans[j];
			if (n > 0) {printf("%lld\n", n); if (--s == 0) return;}
  		}
 	}
}

int main() {
	while (~scanf("%d%d", &c, &s) && s || c) {
		now = 0;
		long long sum = 1;
  		for (int i = 0; i < c; i++) {
			scanf("%d%d", &x[i], &k[i]);
			sum *= k[i];
			if (k[i] * x[now] < k[now] * x[i])
				now = i;
			for (int j = 0; j < k[i]; j++)
				scanf("%d", &y[i][j]);
			sort(y[i], y[i] + k[i]);
  		}
  		if (sum > 10000) solve_enum();
  		else solve_china();
  		printf("\n");
	}
	return 0;
}

UVA 11754 - Code Feat(数论),布布扣,bubuko.com

时间: 2024-10-05 12:23:21

UVA 11754 - Code Feat(数论)的相关文章

uva 11754 - Code Feat(中国剩余定理+暴力)

题目链接:uva 11754 - Code Feat 题目大意:求一个数N,给出C和S,表示有C个条件,每个条件有X 和 k,然后是该个条件的k个yi,即NmodX=yj,输出满足的最小的S个N,要求正整数. 解题思路:total为所有的k的乘积,也就是可以作为一组完整限定条件的可能数,当个确定条件可以用中国剩余定理处理.但是如果total太大的话,处理的情况比较多.不过total数大的时候,可以通过枚举N来判断,找到一组k/x最小的最为枚举基准,然后判断即可. #include <cstdio

UVA 11754 Code Feat (枚举,中国剩余定理)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud C Code Feat   The government hackers at CTU (Counter-Terrorist Unit) have learned some things about the code, but they still haven't quite solved it.They know it's a single, strictly positive

Uva 11754 Code Feat

题意概述: 有一个正整数$N$满足$C$个条件,每个条件都形如“它除以$X$的余数在集合$\{Y_1, Y_2, ..., Y_k\}$中”,所有条件中的$X$两两互质, 你的任务是找出最小的S个解. 数据范围: $1\leq C\leq9, 1 \leq S \leq 10, X \geq 2, 1 \leq k \leq 100, 0 \leq Y_i \leq X$ 分析: 如果每个集合元素个数为1,那么我们直接使用中国剩余定理求解即可. 因此我们想到枚举余数,但是余数的组合最多会有$10

UVA - 11754 Code Feat (分块+中国剩余定理)

对于一个正整数N,给出C组限制条件,每组限制条件为N%X[i]∈{Y1,Y2,Y3,...,Yk[i]},求满足条件的前S小的N. 这道题很容易想到用中国剩余定理,然后用求第k小集合的方法输出答案.但是一取模,孰大孰小就不好控制了,所以行不通.直接枚举所有情况的话,总方案数(所有k的乘积)高达C*k,显然也是不行的. 还有一种方法是枚举所有可能的N,然后检验是否满足条件.对于每个满足条件的N,任取某个限制条件i,对于其中某个余数j,都可以写成X[i]*t+Y[i][j]的形式.复杂度未知,但总方

uva 11557 - Code Theft(KMP)

题目链接:uva 11557 - Code Theft 题目大意:给定n个文本,每个文本有一个文本名,现在给出一个文本,求给定文本和n个文本中连续相同行数最大值,并且输出文本名,注意为0时不用输出其它的文本名. 解题思路:将每个字符串用映射成一个hash值,然后对匹配文本枚举后缀,建立失配数组进行KMP匹配,记录下每个文本的匹配最大值. #include <cstdio> #include <cstring> #include <map> #include <st

UVA 11557 - Code Theft (KMP + HASH)

UVA 11557 - Code Theft 题目链接 题意:给定一些代码文本,然后在给定一个现有文本,找出这个现有文本和前面代码文本,重复连续行最多的这些文本 思路:把每一行hash成一个值,然后对于每一个文本计算最大匹配值,枚举后缀,然后利用KMP去找即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <string> #include <iostream&g

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