这类问题是给定了能出现哪些数字或者不能出现哪些数字...然后问一个数的最少多少倍可以满足条件...
这个是昨天模拟去年杭州现场赛时碰到的...我以为不会有太多位(猜测50)..然后用数位DP来推...结果WA出翔..主要是位数可能会相当长..看后来的其他题目500+都可能的..数位DP绝对跪....
正解是BFS+Hash...Hash指的是对于每个数字作为最后一个数字..能得到哪些余数..hash[10][MOD]..这样就能看出其实总的状态是有限的...并且不多..为了找到答案..那么从第一位开始BFS直到出来解就行...
Ural - 1495
题意:
给出一个数...问起最小的倍数得到的数让其只含1和2...没有或者长度大于30位..则输出Impossible.
Program:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#define ll long long
#define oo 1<<29
#define pi acos(-1.0)
#define MAXN 1000005
#define esp 1e-30
using namespace std;
struct node
{
int x,s,L;
};
int pre[3][MAXN][2];
queue<node> Q;
void dfs(int x,int s)
{
if (x==-1) return;
dfs(pre[x][s][0],pre[x][s][1]);
printf("%d",x);
}
void BFS(int MOD)
{
int t;
node h,k;
memset(pre,-0x7f,sizeof(pre));
while (!Q.empty()) Q.pop();
for (t=1;t<3;t++)
h.x=t,h.s=t%MOD,h.L=1,Q.push(h),pre[h.x][h.s][0]=-1;
while (!Q.empty())
{
h=Q.front(),Q.pop();
if (h.L>30) break;
if (!h.s)
{
dfs(h.x,h.s);
printf("\n");
return;
}
for (t=1;t<3;t++)
{
k.x=t,k.s=(h.s*10+t)%MOD,k.L=h.L+1;
if (pre[k.x][k.s][0]>=-1) continue;
pre[k.x][k.s][0]=h.x,pre[k.x][k.s][1]=h.s;
Q.push(k);
}
}
puts("Impossible");
}
int main()
{
int n;
scanf("%d",&n),BFS(n);
return 0;
}
POJ 1465,HDU 4474
题意:
这两题是差不多的意思(POJ1465是给出哪些数字能用..HDOJ是给出哪些数字不能用)...意思是限制了能用哪些数字..现在给出一个数N..问其最小的倍数得到的数仅有能用的数字组成
Program(POJ 1465):
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#define ll long long
#define oo 1<<29
#define pi acos(-1.0)
#define MAXN 5505
#define esp 1e-30
using namespace std;
struct node
{
int x,s;
};
bool f[10];
int pre[10][MAXN][2];
queue<node> Q;
void dfs(int x,int s)
{
if (x==-1) return;
dfs(pre[x][s][0],pre[x][s][1]);
printf("%d",x);
}
void BFS(int MOD)
{
int t;
node h,k;
if (!MOD)
{
puts("0");
return;
}
memset(pre,-0x7f,sizeof(pre));
while (!Q.empty()) Q.pop();
for (t=1;t<10;t++)
if (f[t])
h.x=t,h.s=t%MOD,Q.push(h),pre[h.x][h.s][0]=-1;
while (!Q.empty())
{
h=Q.front(),Q.pop();
if (!h.s)
{
dfs(h.x,h.s);
printf("\n");
return;
}
for (t=0;t<10;t++)
if (f[t])
{
k.x=t,k.s=(h.s*10+t)%MOD;
if (pre[k.x][k.s][0]>=-1) continue;
pre[k.x][k.s][0]=h.x,pre[k.x][k.s][1]=h.s;
Q.push(k);
}
}
puts("0");
}
int main()
{
int n,m,x;
while (~scanf("%d%d",&n,&m))
{
memset(f,false,sizeof(f));
while (m--) scanf("%d",&x),f[x]=true;
BFS(n);
}
return 0;
}
Program(HDU 4474):
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include <stack>
#include<queue>
#include<algorithm>
#include<cmath>
#define oo 1000000007
#define MAXN 100005
#define ll long long
#define pi acos(-1.0)
using namespace std;
struct node
{
int x,s,pre;
};
bool f[10],hash[10][10005];
int pre[10][100005][2];
queue<node> Q;
void dfs(int x,int s)
{
if (x==-1) return;
dfs(pre[x][s][0],pre[x][s][1]);
printf("%d",x);
}
void BFS(int MOD)
{
int i;
node h,k;
memset(hash,false,sizeof(hash));
while (!Q.empty()) Q.pop();
memset(pre,-1,sizeof(pre));
for (i=1;i<10;i++)
if (f[i])
h.x=i,hash[i][h.s=i%MOD]=true,Q.push(h);
while (!Q.empty())
{
h=Q.front(),Q.pop();
if (!h.s)
{
dfs(h.x,h.s);
puts("");
return;
}
for (i=0;i<10;i++)
if (f[i])
{
k.x=i,k.s=(h.s*10+i)%MOD;
if (hash[k.x][k.s]) continue;
hash[k.x][k.s]=true;
pre[k.x][k.s][0]=h.x,pre[k.x][k.s][1]=h.s;
Q.push(k);
}
}
puts("-1");
}
int main()
{
int cases=0,x,n,num;
while (~scanf("%d%d",&n,&num))
{
memset(f,true,sizeof(f));
while (num--) scanf("%d",&x),f[x]=false;
printf("Case %d: ",++cases);
BFS(n);
}
return 0;
}
HDU 1226
题意:
给了一个十进制数N,给了一个进制(2~16)..并且给出在这个进制下能用的数字(>=10的用A,B,C,D,E,F标记)..问N最少多少倍得到的数是有所给的字符组成的...
题解:
不管几个进制都是一回事...
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#define ll long long
#define oo 1<<29
#define pi acos(-1.0)
#define MAXN 5505
#define esp 1e-30
using namespace std;
struct node
{
int x,s,L;
};
bool f[16];
int pre[16][MAXN][2];
queue<node> Q;
void DFS(int x,int s)
{
if (x==-1) return;
DFS(pre[x][s][0],pre[x][s][1]);
if (x<10) printf("%d",x);
else printf("%c",x-10+'A');
}
void BFS(int C,int MOD)
{
if (!MOD)
{
if (f[0]) puts("0");
else puts("give me the bomb please");
return;
}
int i,x,t;
node h,k;
memset(pre,-0x2f,sizeof(pre));
while (!Q.empty()) Q.pop();
for (i=1;i<C;i++)
if (f[i])
h.x=i,h.s=i%MOD,h.L=1,Q.push(h),pre[h.x][h.s][0]=-1;
while (!Q.empty())
{
h=Q.front(),Q.pop();
if (h.L>500) break;
if (!h.s)
{
DFS(h.x,h.s);
puts("");
return;
}
for (i=0;i<C;i++)
if (f[i])
{
k.x=i,k.s=(h.s*C+i)%MOD,k.L=h.L+1;
if (pre[k.x][k.s][0]>=-1) continue;
pre[k.x][k.s][0]=h.x,pre[k.x][k.s][1]=h.s;
Q.push(k);
}
}
puts("give me the bomb please");
}
int main()
{
int cases,N,C,M,x;
char c;
scanf("%d",&cases);
while (cases--)
{
scanf("%d%d%d",&N,&C,&M);
memset(f,false,sizeof(f));
while (M--)
{
do { c=getchar(); } while (c==' ' || c=='\n');
if (c>='0' && c<='9')
{
x=0;
while (c>='0' && c<='9')
{
x=x*10+c-'0';
c=getchar();
}
}else
x=10+c-'A';
f[x]=true;
}
BFS(C,N);
}
return 0;
}