uva11754 Code Feat

来源:互联网 发布:java udp编程和 tcp 编辑:程序博客网 时间:2024/05/18 01:58

Hooray! Agent Bauer has shot the terrorists, blown up the bad guy
base, saved the hostages, exposed the moles in the government,
prevented an environmental catastrophe, and found homes for three
orphaned kittens, all in the span of 19 consecutive hours. But now, he
only has 5 hours remaining to deal with his nal challenge: an
activated nuclear bomb protected by a security code. Can you help him
gure out the code and deactivate it? Events occur in real time. 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, integer. They also know several
clues of the form \when divided by X , the remainder is one of f Y 1
;Y 2 ;Y 3 ;:::;Y k g “. There are multiple solutions to these clues,
but the code is likely to be one of the smallest ones. So they’d like
you to print out the rst few solutions, in increasing order. The
world is counting on you! Input Input consists of several test cases.
Each test case starts with a line containing C , the number of clues
(1  C  9), and S , the number of desired solutions (1  S  10).
The next C lines each start with two integers X (2  X ) and k (1  k
 100), followed by the k distinct integers Y 1 , Y 2 , … , Y k (0
 Y 1 ;Y 2 ;:::;Y k < X ). You may assume that the X ‘s in each test
case are pairwise relatively prime (ie, they have no common factor
except 1). Also, the product of the X ‘s will t into a 32-bit
integer. The last test case is followed by a line containing two
zeros. Output For each test case, output S lines containing the S
smallest positive solutions to the clues, in increasing order. Print a
blank line after the output for each test case.

有两种解法,第一种是直接枚举每个集合中取哪个元素,然后用中国剩余定理,复杂度O(πklogπk)。
另一种是找到一个k/x最小的条件【让枚举的解尽可能稀疏】,直接枚举解去验证,复杂度不好估计,但是在πk比较大的时候,解的分布比较密集,速度不会太慢。
当πk比较小的时候选择第一种,否则选择第二种,就可以过了。

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;#define LL long longconst int c=10000;LL yy[12][110],xx[12],ans[100010],M,a[12];int kk[12],n,s,tot;void init(){    int i,j;    for (i=1;i<=n;i++)    {        scanf("%lld%d",&xx[i],&kk[i]);        for (j=1;j<=kk[i];j++)          scanf("%lld",&yy[i][j]);        sort(yy[i]+1,yy[i]+kk[i]+1);    }}void gcd(LL a,LL b,LL &x,LL &y){    if (!b)    {        x=1;        y=0;        return;    }    gcd(b,a%b,y,x);    y-=a/b*x;}void dfs(int now){    int i;    LL p,q,x=0;    if (now==n+1)    {        for (i=1;i<=n;i++)        {            gcd(M/xx[i],xx[i],p,q);            p=(p%M+M)%M;            x=(x+M/xx[i]*p%M*a[i]%M)%M;        }        ans[++tot]=x;    }    else      for (i=1;i<=kk[now];i++)      {          a[now]=yy[now][i];          dfs(now+1);      }}void solve1(){    int i,j;    M=1;    for (i=1;i<=n;i++)      M*=xx[i];    tot=0;    dfs(1);    sort(ans+1,ans+tot+1);    for (i=0;s;i++)      for (j=1;j<=tot&&s;j++)      if (M*i+ans[j])      {        printf("%lld\n",M*i+ans[j]);        s--;      }}void solve2(){    int i,j,k,p=1,l,r,mid;    bool flag;    LL x,tem;    double now=(double)kk[1]/xx[1];    for (i=2;i<=n;i++)      if ((double)kk[i]/xx[i]<now)      {        p=i;        now=kk[i]/xx[i];      }    for (i=0;s;i++)      for (j=1;j<=kk[p]&&s;j++)      {        x=i*xx[p]+yy[p][j];        if (!x) continue;        flag=1;        for (k=1;k<=n&&flag;k++)        {            tem=x%xx[k];            l=1;            r=kk[k];            while (l<r)            {                mid=(l+r)/2;                if (yy[k][mid]>=tem) r=mid;                else l=mid+1;            }            flag=(yy[k][l]==tem);        }        if (flag)        {            printf("%lld\n",x);            s--;        }      }}int main(){    int i;    LL t;    while (scanf("%d%d",&n,&s)&&n)    {        init();        t=1;        for (i=1;i<=n;i++)          t*=kk[i];        if (t<=c) solve1();        else solve2();        putchar('\n');    }}
0 0
原创粉丝点击