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]的形式。复杂度未知,但总方案数很大的时候可以较快得出答案。

可以用分块的思想,设定一个合适的阈值,当总方案数超过某个阈值的时候用枚举,否则就用中国剩余定理。

 1 #include<bits/stdc++.h>
 2
 3 using namespace std;
 4 typedef long long ll;
 5 const ll N=9+2;
 6 vector<ll> v[N],w;
 7 set<ll> st[N];
 8 ll m[N],e[N],n,k,K;
 9
10 void exgcd(ll a,ll b,ll& x,ll& y,ll& g) {
11     if(!b)x=1,y=0,g=a;
12     else exgcd(b,a%b,y,x,g),y-=x*(a/b);
13 }
14
15 ll inv(ll x,ll mod) {
16     ll a,b,g;
17     exgcd(x,mod,a,b,g);
18     return (a+mod)%mod;
19 }
20
21 ll check(ll x) {
22     for(ll i=0; i<n; ++i)if(!st[i].count(x%m[i]))return 0;
23     return 1;
24 }
25
26 void solve1() {
27     ll p=0;
28     for(ll i=1; i<n; ++i)if(v[i].size()*m[p]<v[p].size()*m[i])p=i;
29     for(ll t=0; w.size()<k; ++t)
30         for(ll i=0; i<v[p].size()&&w.size()<k; ++i)
31             if(t*m[p]+v[p][i]&&check(t*m[p]+v[p][i]))w.push_back(t*m[p]+v[p][i]);
32 }
33
34 void solve2() {
35     ll M=1;
36     for(ll i=0; i<n; ++i)M*=m[i];
37     for(ll i=0; i<n; ++i)e[i]=M/m[i]*inv(M/m[i],m[i]);
38     for(ll S=0; S<K; ++S) {
39         ll S2=S,x=0;
40         for(ll i=0; i<n; ++i) {
41             ll j=S2%v[i].size();
42             S2/=v[i].size();
43             x=(x+e[i]*v[i][j])%M;
44         }
45         w.push_back(x?x:x+M);
46     }
47     sort(w.begin(),w.end());
48     w.resize(unique(w.begin(),w.end())-w.begin());
49     for(ll i=0; w.size()<k; ++i)w.push_back(w[i]+M);
50 }
51
52 int main() {
53     while(scanf("%lld%lld",&n,&k)&&n) {
54         for(ll i=0; i<N; ++i)v[i].clear();
55         for(ll i=0; i<N; ++i)st[i].clear();
56         K=1;
57         for(ll i=0; i<n; ++i) {
58             scanf("%lld",&m[i]);
59             ll t;
60             scanf("%lld",&t);
61             K*=t;
62             while(t--) {
63                 ll x;
64                 scanf("%lld",&x);
65                 v[i].push_back(x);
66                 st[i].insert(x);
67             }
68             sort(v[i].begin(),v[i].end());
69         }
70         w.clear();
71         K>10000?solve1():solve2();
72         for(ll i=0; i<k; ++i)printf("%lld\n",w[i]);
73         printf("\n");
74     }
75     return 0;
76 }

原文地址:https://www.cnblogs.com/asdfsag/p/10353549.html

时间: 2024-08-01 05:38:26

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(数论)

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

如果直接枚举的话,枚举量为k1 * k2 *...* kc 根据枚举量的不同,有两种解法. 枚举量不是太大的话,比如不超过1e4,可以枚举每个集合中的余数Yi,然后用中国剩余定理求解.解的个数不够S个的时候,要把这些解分别加上M.2M...(M = X1 * X2 *...* Xc) 如果上述枚举量太大的话,直接枚举x.找一个k/X最小的条件,然后让x = t * X + Yi开始枚举,因为这样枚举x增长得最快,所以枚举次数也就最少.如果符合要求的话则输出. 上面两种方法都要注意所找到的解为正整

UVA 11754 (暴力+中国剩余定理)

题目链接: http://www.bnuoj.com/v3/problem_show.php?pid=20172 题目大意:有C个模方程,每个方程可能有k余数,求最小的S个解. 解题思路: 看见模方程就想到中国剩余定理,然后看下确定的方程情况. 由乘法原理,共有II ki 种情况,即求解II ki 次.k比较大时基本完蛋. 其实解模方程还有一种暴力方法,就是选定一个模方程,令t=0,1...., n=t*LCM+余数(n一定要大于0) 通过t不断增大这种迭代方式从小到大创造一些可能解n,然后去测

uva 756 - Biorhythms(中国剩余定理)

题目链接:uva 756 - Biorhythms 题目大意:三个周期,23,28,33,输入为分别为在新一年中(三个周期均从0开始),出现周期中峰值的一天,以及当前的日子,问说需要经过多少天,才能使得三个峰值的在同一天. 解题思路:裸的中国剩余定理. #include <cstdio> #include <cstring> typedef long long ll; const int maxn = 5; const ll m[maxn] = {23,28,33}; ll M,

UVA11754 - Code Feat

Hooray!  Agent Bauer has shot the terrorists, blown upthe bad guy base, saved the hostages, exposed the moles in the government,prevented an environmental catastrophe, and found homes for three orphanedkittens, all in the span of 19 consecutive hours

中国剩余定理小结 (互质,非互质) (poj 1006,hdu 3579)

先证明下中国剩余定理 条件: x%m_1=a_1 x%m_2=a_2 ... x%m_n=a_n m_1,m_2,...,m_n两两互质 证明: 设M=m_1*m_2*m_3*...*m_n M_i=M/m_i 因为gcd(M_i,m_i)=1,所以M_ix+m_iy=1 (t_i*M_i)%m_i=1 //由Ext_gcd(M_i,m_i,x,y)求出,t_i=x 方程组的解:x=a_1*t_1*M_1+...+a_n*t_n*M_n 题目:poj 1006 http://poj.org/pr