题意
每个测试例,给出一系列数和一个幸运数字,如果这个数能等于若干小于它的并且含有幸运数字的数之和,输出YES,否则NO。
注意数据规模非常大,暴力是不能的。既然是数学题,必然要用到一些技巧。目前能力有限,只能看出规律,而无法严格证明。
规律:
设
幸
运
数
字
为
d
,
如
果
正
整
数
x
≥
10
d
,
则
存
在
∑
y
i
=
x
(
y
i
≤
x
,
y
i
=
⋯
d
⋯
⏟
)
y
i
小
于
等
于
x
,
且
某
一
位
含
有
d
设幸运数字为d,如果正整数x \geq 10d,\\则存在 \sum y_i=x\\(y_i\leq x,y_i= \underbrace {\cdots d \cdots})\\y_i小于等于x,且某一位含有d
设幸运数字为d,如果正整数x≥10d,则存在∑yi=x(yi≤x,yi=
⋯d⋯)yi小于等于x,且某一位含有d
举例
d=9
x=100=91+9
x=201=192+9
x=303=294+9
x=12345=12296+49
当x>=10d,可用低位灵活变换,总能凑出一个满足的答案
cf题解用的迷之dp,实在看不懂。对于其他范围内,采用dfs暴力破解,也能过,就是慢了些,等想出更好的方法再更改。
//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
#define ff first
#define ss second
#define ms(x) memset(x,0,sizeof(x))
typedef long long ll;
typedef pair<int,int> pii;
#define inf 0x3f3f3f3f //10 6110 9567<2^30=10 7374 1824
#define iinf 0x7fffffff //
const int mod=1e9+7;
const int MAX=1e5;
bool flag;
bool pd(int x,int d){
while(x){
if(x%10==d)return true;
x/=10;
}
return false;
}
void dfs(int x,int d){
if(x==d||x==0){flag=true;return;}
else if(x<d)return;
for(int i=x;i>=d;i--){
if(pd(i,d)){
x-=i;
dfs(x,d);
x+=i;
}
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
int n,d,x;
cin>>n>>d;
while(n--){
flag=false;
cin>>x;
if(x>=d*10)cout<<"YES\n";
else{
dfs(x,d);
if(flag)cout<<"YES\n";
else cout<<"NO\n";
}
}
}
}