题目描述
Alice 最近得到了一个正整数 x。由于 Bob 的生日马上就要到了,Alice 准备把 x 作为 Bob 的生日礼物。
然而 Bob 只喜欢完全平方数,Alice 为了让 Bob 开心,打算对 x 进行一些修改。每次 Alice 可以对 x 进行如下的一种修改:
- 将 x 10进制表示下(不含前导 0)的一个数字修改成 0, 1, ..., 9 中的一个。例如 123 可以变成 133,1001可以变成 1。
2.将 x 10进制表示下(不含前导 0)的一个数字删去。例如 123 可以变成 23, 13,1001 可以变成 1。
注意,必须保证修改后的数字 x 仍然是正整数。
由于 Bob 的生日很快就要到了,Alice 想知道最少进行多少次操作(可以不操作)可以将数字 x 变成完全平方数。
完全平方数的定义:我们成一个数 x 是完全平方数,当且仅当存在一个自然数 y 使得 x = y2。
输入输出格式
输入格式:
每个测试点共 T 组数据。
第一行一个正整数 T。
接下来 T 行,每行一个正整数 x,如题面所述。
输出格式:
输出共 T 行,每行一个整数表示答案。
输入输出样例
3 1 12 9004
0 1 1
说明
对于 30% 的数据 1 ≤ n ≤ 100。
对于 100% 的数据 1 ≤ n ≤ 1000000, 1 ≤ T ≤ 1000。
估计看一眼就想到搜索,其实标程也许比你想象中的还暴力!
标程:
bfs,对于队列中的每个数,在枚举在每个位置上进行一种转换,(就是当前数以一个代价所能转移到的数),然后就可以A了,可以A了,可以A了!
我的解法:
一. 基本想法是:枚举 X 的十进制中每个位置上的变换,分别是(1.不变;2.删除;3.变成 0~9 中的任意一个)。它的时间复杂度是 O(T*126),显然不能够接受。
二. 考虑优化,基于折半搜索的思想,我们可以对转移的目标(完全平方数)做些预处理。
三. 具体而言,我们构造十二进制数,其中十个数分配给十进制数(0~9),另外两位分别用于表示删除和维护位数。
四. 预处理就是枚举每个完全平方数可以被哪些数通过改变某些位置上的数变成它,并将它们打上标记。
五. 计算答案就是枚举每个位数上的变换方式,最终用十二进制数表示变换完的数经过了哪些变换,然后与预处理过的数对应。
时间复杂度:O(1000 * 2 Λ 6 + T * 3 Λ 6)。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,x,ans,tmp,wq,ss[10],base[10]; 4 bool vis[43000050]; 5 int hw(int u) 6 { 7 int sum=0; 8 while(u) 9 { 10 ++sum; 11 ss[sum]=u%10+1; 12 u/=10; 13 } 14 return sum; 15 } 16 void dfs1(int u,int now) 17 { 18 if(u>wq) 19 { 20 for(int i=u-1;i<=6;++i) 21 { 22 vis[now]=true; 23 now+=1*base[i+1]; 24 } 25 return ; 26 } 27 dfs1(u+1,now+ss[u]*base[u]); 28 dfs1(u+1,now+11*base[u]); 29 } 30 void dosomethingfirst() 31 { 32 base[1]=1; 33 for(int i=2;i<=7;++i) 34 base[i]=base[i-1]*12; 35 for(int i=1;i<1000;++i) 36 { 37 tmp=i*i; 38 wq=hw(tmp); 39 dfs1(1,0); 40 } 41 for(int i=1;i<=6;++i) 42 vis[0]=false; 43 } 44 void dfs2(int u,int sum,int now,int p) 45 { 46 if(sum>=ans) 47 return ; 48 if(u>wq) 49 { 50 if(vis[now]) 51 ans=sum; 52 return ; 53 } 54 dfs2(u+1,sum,now+ss[u]*base[p+1],p+1); 55 dfs2(u+1,sum+1,now+11*base[p+1],p+1); 56 dfs2(u+1,sum+1,now,p); 57 } 58 int main() 59 { 60 dosomethingfirst(); 61 scanf("%d",&n); 62 for(int i=1;i<=n;++i) 63 { 64 ans=1000050; 65 scanf("%d",&x); 66 if(x==1000000) 67 ans=0; 68 else 69 { 70 wq=hw(x); 71 dfs2(1,0,0,0); 72 } 73 printf("%d ",ans); 74 } 75 return 0; 76 }