[枚举] Jzoj P3387 终极武器

Description

  经过一番周折,精英队伍的队员们终于来到了关押applepi的牢狱面前。心中神一般的领袖applepi就在眼前,队员们都不由自主地跪烂膝盖……不过令他们沮丧的是,牢狱的大锁没有钥匙孔,黑魔法师Vani根本就没有指望它再被打开。幸好队员们携带了新研制的终极武器——k型氙激光器(Xenon Laser - k,代号XLk),可以用来破拆这把锁。不过作为一道终极武器,它的启用规则异常严格。
  Xenon Laser - k上共有N个波段能够发射激光,每个波段可以用一个闭区间[ai,bi]来表示,其中ai,bi为正整数,b[i-1]<ai≤bi。对于两个数字p和q,如果对于这N个波段内的任意一个整数num,把它在十进制表示下的后k位中某一位上的p换成q(或者q换成p),都满足得到的整数仍然在这N个波段内,那么称在该激光器中,数字p和q是k等价的。我们称两两之间k等价的数字组成一个k等价类。
  激光器附带了9个发射匣,代表1~9这9个数字。只有把同一个等价类的数字对应的发射匣安置在一排上,Xenon Laser - k才能够启动。给定个波段,现在就请你求出1~9这9个数字分成了哪些等价类,并且每行输出一个等价类。
  本题描述比较抽象,请参考样例解释。
 

Input

第一行两个整数N,k。

接下来N行每行两个整数ai,bi。ai,bi为正整数,满足b[i-1]<ai<=bi。

Output

每行一个等价类,各行之内都按照数字从小到大排序,数字中间没有空格,行与行之间按照等价类中最小的数字从小到大排序。具体格式参考样例。
 

Sample Input

样例输入1

1 1

1 566

样例输入2

1 2

30 75

Sample Output

样例输出1

123456

789

样例输出2

12

345

6

7

89

样例解释:

第一个样例中,只允许修改个位。对于1~559这些数,个位无论如何修改都在波段内。对于560~566这些数,个位修改为大于等于7的数字时(例如562的2修改为8),就不在波段内了。因此1~6和7~9属于不同的等价类。

第二个样例每一位上都可以修改。修改方法与上面一个样例类似。

 
 

Data Constraint

对于25% 的数据,1<=n<=50,1<=ai<=bi<=6000。

对于另25% 的数据,n=1。

对于另30% 的数据,k=1。

对于100% 的数据,1<=n<=10000,1<=k<=19,1<=ai<=bi<=10^18。

在所有的数据中,均匀分布着25% 的随机数据。

 

 

题解

  • 首先,对于这题,我们可以发现,如果x[i]与y[i]差的和<10000000,可以直接枚举合法的数
  • 将它们每一位数都截出来,将每一位上出现过什么都+1
  • 最后枚举i,j,如果判断是否是等类的呢?
  • 枚举每一位上,如果全部位上出现的次数都相等的话
  • 两个数字就是等类的
  • 然后再来考虑一下a[i]与b[i]的差>10000000
  • 我们可以从一个为被访问过的数,往后拓展,再判断两者是否合法
  • 那如果判断是否合法呢?
  • ①对于y[i]-x[i]<100000
  • 暴力枚举一个j(0<=j<=y[i]-x[i])
  • 设t=x[i]+j
  • 如果现在是判断a,b是否等类
  • 从后往前将t每一位截出来
  • 如果t==a,那么使p=w-a*i+b*i(i就是当前从后往前截到哪一位)
  • 然后再所有x[i],y[i]的区间里跑,如果w在一个区间内,就是等类的
  • 设t=y[i]-j
  • 类似于上面的判断
  • ②对于y[i]-x[i]>100000
  • 枚举一个j(0<=j<=10000)
  • 向上面一样判断一下

代码

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<cctype>
  7 using namespace std;
  8 long long n,k,visit[10],x[10010],y[10010],sum,f[100][13],a[10][20];
  9 long long read()
 10 {
 11     long long X=0,w=0; 
 12     char ch=0;
 13     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
 14     while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
 15     return w?-X:X;
 16 }
 17 void doit(long long x)
 18 {
 19     long long t=x,len=1;
 20     while (t)
 21     {
 22         if (len>k) break;
 23         f[len][t%10]++; t=t/10; len++;
 24     }
 25 }
 26 bool pd(long long a,long long b)
 27 {
 28     for (long long i=1;i<=k;i++)
 29         if (f[i][a]!=f[i][b]) 
 30             return 0;
 31     return 1;
 32 }
 33 void work()
 34 {
 35     for (long long i=1;i<=n;i++)
 36         for (long long j=x[i];j<=y[i];j++)
 37             doit(j);
 38     for (long long i=1;i<=9;i++)
 39         if (!visit[i])
 40         {
 41             printf("%d",i);
 42             for (long long j=i+1;j<=9;j++) 
 43                 if (pd(i,j))
 44                 {
 45                     visit[j]=1;
 46                     printf("%d",j);
 47                 }
 48             printf("\n");
 49         }
 50 }
 51 bool find(long long a)
 52 {
 53     for (long long i=1;i<=n;i++)
 54         if (a>=x[i]&&a<=y[i]) return 1;
 55     return 0;
 56 }
 57 bool check(long long x,long long a,long long b)
 58 {
 59     long long w=x,p=1;
 60     long long len=1;
 61     while (w)
 62     {
 63         if (len>k) break;
 64         if (w%10==a) if (!find(x-a*p+b*p)) return 0;
 65         w=w/10; p=p*10; len++;
 66     }
 67     return 1;
 68 }
 69 bool pd1(long long a,long long b)
 70 {
 71     for (long long i=1;i<=n;i++)
 72     {
 73         if (y[i]-x[i]>100000)
 74         {
 75             for (long long j=0;j<10000;j++)
 76                 if ((check(x[i]+j,a,b)&&check(x[i]+j,b,a)&&check(y[i]-j,a,b)&&check(y[i]-j,b,a))==0) return 0;
 77         }
 78         else 
 79         {
 80             for (long long j=0;j<=y[i]-x[i];j++)
 81             {
 82                 if (j<=10||(x[i]+j)%10==0)
 83                 {
 84                     if ((check(x[i]+j,a,b)&&check(x[i]+j,b,a)&&check(y[i]-j,a,b)&&check(y[i]-j,b,a))==0) return 0;
 85                 }
 86                 else 
 87                 {
 88                     long long w=x[i]+j;
 89                     if (w%10==a)
 90                     {
 91                         if (find(w-a+b)==0) return 0;
 92                     }
 93                     else 
 94                         if (w%10==b)
 95                         {
 96                             if (find(w+a-b)==0) return 0;
 97                         }
 98                 }
 99             }
100         }
101     }
102     return 1;
103 }
104 void dfs(long long x,long long y)
105 {
106     if (y>9) return;
107     if (pd1(x,y)) a[x][++a[x][0]]=y,visit[y]=1;
108     dfs(x,y+1);
109 }
110 void work1()
111 {
112     for (long long i=1;i<=9;i++)
113         if (!visit[i])
114         {
115             a[i][++a[i][0]]=i;
116             visit[i]=1;
117             dfs(i,i+1);
118         }
119     for (long long i=1;i<=9;i++)
120         if (a[i][0])
121         {
122             for (long long j=1;j<=a[i][0];j++) printf("%d",a[i][j]);
123             printf("\n");
124         }
125 }
126 int main()
127 {
128     n=read();k=read();
129     for (long long i=1;i<=n;i++) x[i]=read(),y[i]=read(),sum+=y[i]-x[i];
130     if (sum<10000000)
131     {
132         work();
133         return 0;
134     }
135     else 
136     {
137         work1();
138         return 0;
139     }
140 }

 

posted @ 2018-07-14 10:10  BEYang_Z  阅读(276)  评论(0编辑  收藏  举报