题目大意:
上共有
个波段能够发射激光,每个波段可以用一个闭区间
来表示,其中
为正整数,
。对于两个数字
和
,如果对于这
个波段内的任意一个整数
,把它在十进制表示下的后
位中某一位上的
换成
(或者
换成
),都满足得到的整数仍然在这
个波段内,那么称在该激光器中,数字
和
是
等价的。我们称两两之间
等价的数字组成一个k等价类。
激光器附带了
个发射匣,代表
~
这
个数字。只有把同一个等价类的数字对应的发射匣安置在一排上,Xenon Laser - k才能够启动。给定个波段,现在就请你求出
~
这
个数字分成了哪些等价类。
分析:
当
,可以直接枚举合法的数
将它们每一位数都截出来,将每一位上出现过什么都
然后枚举
,
判断是否是等价类,
枚举每一位上,如果全部位上出现的次数都相等的话
两个数字就是等类的
当
我们可以从一个为被访问过的数,往后拓展,再判断两者是否合法
如何判断合法
①对于
枚举一个
设
如果现在是判断
是否等价类
从后往前将
每一位截出来
如果
,那么使
(i就是当前从后往前截到哪一位)
然后再所有x[i],y[i]的区间里跑,如果w在一个区间内,就是等类的
设
,然后同上
②对于
那么
枚举
,操作同上
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define fo(i, a, b) for (i = a; i <= b; i++)
#define N 10005
#define M 10
using namespace std;
typedef long long ll;
ll a[M][M], mul[25], cnt[M], vis[M], x[N], y[N];
int f[25][15], n, k;
void read(ll &xx)
{
ll f=1;xx=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){xx=xx*10+s-'0';s=getchar();}
xx*=f;
}
void Jud(ll x) {
ll y = x;
int len = 1;
for (; y; y /= 10) {
if (len > k) break;
++f[len][y%10], ++len;
}
}
bool Flag(int a, int b) {
int i;
fo(i, 1, k)
if (f[i][a] != f[i][b]) return 0;
return 1;
}
bool Get_inout(ll a) {
int i;
fo(i, 1, n) if (a >= x[i] && a <= y[i]) return 1;
return 0;
}
bool pan(ll x, ll a, ll b) {
ll y = x, len = 1, p = 1;
for (; y; y /= 10) {
if (len > k) break;
if (y%10 == a)
if (!Get_inout(x-a*mul[len-1]+b*mul[len-1])) return 0;
++len;
}
return 1;
}
bool Check(ll a, ll b) {
int i, j;
fo(i, 1, n)
if (y[i] - x[i] > 10000) {
fo(j, 0, 9999)
if (!pan(x[i]+j, a, b) || !pan(x[i]+j, b, a) ||
!pan(y[i]-j, a, b) || !pan(y[i]-j, b, a)) return 0;
} else {
fo(j, 0, y[i]-x[i]) {
if (j <= 10 || (x[i]+j)%10 == 0) {
if (!pan(x[i]+j, a, b) || !pan(x[i]+j, b, a) ||
!pan(y[i]-j, a, b) || !pan(y[i]-j, b, a)) return 0;
} else {
ll w=x[i]+j;
if (w%10 == a) {
if (!Get_inout(w-a+b)) return 0;
} else if (w%10 == b) {
if (!Get_inout(w+a-b)) return 0;
}
}
}
}
return 1;
}
void dfs(ll x, ll y) {
if (y > 9) return;
if (Check(x, y)) a[x][++cnt[x]] = y, vis[y] = 1;
dfs(x, y+1);
}
int main() {
int i;
scanf("%d %d", &n, &k);
ll sum = 0;
fo(i, 1, n) read(x[i]), read(y[i]), sum += (y[i] - x[i]);
mul[0] = 1;
fo(i, 1, 20) mul[i] = mul[i-1]*10;
if (sum < 1e7) {
ll j;
fo(i, 1, n)
fo(j, x[i], y[i]) Jud(j);
fo(i, 1, 9)
if (!vis[i]) {
printf("%d", i);
fo(j, i+1, 9)
if (Flag(i,j)) vis[j] = 1, printf("%d",j);
printf("\n");
}
} else {
int j;
fo(i, 1, 9)
if (!vis[i]) a[i][++cnt[i]] = i, vis[i] = 1, dfs(i, i+1);
fo(i, 1, 9)
if (cnt[i]) {
fo(j, 1, cnt[i]) printf("%d", a[i][j]); printf("\n");
}
}
return 0;
}