Codeforces_1478B

Codeforces_1478B_第1张图片
Codeforces_1478B_第2张图片

题意

每个测试例,给出一系列数和一个幸运数字,如果这个数能等于若干小于它的并且含有幸运数字的数之和,输出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 dx10dyi=x(yix,yi= d)yixd

举例

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
#include
#include
#include
#include
#include
#include
#include
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";
            }
        }
    }
}

你可能感兴趣的:(数学入门,数学,dfs)