Description
Petka thought of a positive integer n and reported to Chapayev the sum of its digits and the sum of its squared digits. Chapayev scratched his head and said: "Well, Petka, I won't find just your number, but I can find the smallest fitting number." Can you do the same?
Input
The first line contains the number of test cases t (no more than 10000). In each of the following t lines there are numbers s1 and s2 (1 ≤ s1, s2 ≤ 10000) separated by a space. They are the sum of digits and the sum of squared digits of the number n.
Output
For each test case, output in a separate line the smallest fitting number n, or "No solution" if there is no such number or if it contains more than 100 digits.
Sample Input
4 9 81 12 9 6 10 7 9
Sample Output
9 No solution 1122 111112
思路:预处理广搜。从0 0 开始搜索、每个dp[i][j]只用进队一次。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <string>
#include <string>
using namespace std;
#define maxn 108
bool dp[902][8102];
int pre[902][8102];
int ans[102];
struct Item
{
int step,ss1,ss2;
Item(){}
Item(int s,int s1,int s2)
{
step = s;
ss1 = s1;
ss2 = s2;
}
};
queue <Item> q;
void init()
{
memset(dp,0,sizeof(dp));
dp[0][0] = 0;
memset(pre,-1,sizeof(pre));
q.push(Item(0,0,0));
while(!q.empty())
{
Item item = q.front();
q.pop();
if(item.step >= 100) break;
for(int i = 1;i <= 9;i++)
{
int nows1 = item.ss1 + i;
int nows2 = item.ss2 + i*i;
if(dp[nows1][nows2]) continue;
if(nows1 > 900 || nows2 > 8100) break;
dp[nows1][nows2] = 1;
pre[nows1][nows2] = i;
q.push(Item(item.step+1,nows1,nows2));
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
init();
int t; scanf("%d",&t);
while(t--)
{
int s1,s2;
scanf("%d%d",&s1,&s2);
if(s1 > 900 || s2 > 8100)
{
printf("No solution\n");
continue;
}
if(pre[s1][s2] == -1) printf("No solution\n");
else
{
int pos = 0;
while(pre[s1][s2] != -1)
{
ans[pos++] = pre[s1][s2];
int as = s1,bs = s2;
s1 -= pre[as][bs];
s2 -= pre[as][bs]*pre[as][bs];
}
for(int i = pos-1;i >= 0;i--) printf("%d",ans[i]);
printf("\n");
}
}
return 0;
}