Codeforces55 D.美しい数(デジタルdp +数論の知識)

題名:

ここに画像の説明を挿入

解決:

显然数位只有[1,9].

一些本题需要的数论知识:
1.如果x同时是a,b,c的倍数,那么x是lcm(a,b,c)的倍数.
2.[1,9]的lcm等于2520.

因此满足条件的数x,设x的数位lcm=mod,
那么x%mod=0一定成立,

令d[len][pre][mod]:
1.数位剩余长度len,
2.数的和已经有pre,
3.当前数位lcm为mod,
的方案数.

第一维只有20,
第二维只需要存%2520的结果,因为膜数位lcm等于0的数,一定%2520=0.
第三维度其实只需要存50,因为[1,9]组合的不同lcm其实只有不到50.

定义出状态,之后就是简单的数位dp了.

コード:

#include<bits/stdc++.h>
#define int long long
#define PI pair<int,int>
using namespace std;
const int maxm=2e6+5;
const int lc1=2520;//[1,9]的lcm=2520.
int d[20][2555][55];
int mp[2555],tot;
int digit[20];
void init(){
    
    
    memset(d,-1,sizeof d);
    for(int i=1;i<=lc1;i++){
    
    
        if(lc1%i==0){
    
    
            mp[i]=++tot;//数位的lcm只有tot种,位置是离散的,哈希成连续的
        }
    }
}
int lcm(int a,int b){
    
    
    return a/__gcd(a,b)*b;
}
int dfs(int len,int limit,int pre,int mod){
    
    
    if(!len)return pre%mod==0;
    if(!limit&&d[len][pre][mp[mod]]!=-1)return d[len][pre][mp[mod]];
    int ans=0;
    int ma=(limit?digit[len]:9);
    for(int i=0;i<=ma;i++){
    
    
        ans+=dfs(len-1,limit&&i==ma,(pre*10+i)%lc1,i==0?mod:lcm(mod,i));
    }
    if(!limit)d[len][pre][mp[mod]]=ans;
    return ans;
}
int sol(int x){
    
    
    int len=0;
    while(x){
    
    
        digit[++len]=x%10;
        x/=10;
    }
    return dfs(len,1,0,1);
}
void solve(){
    
    
    int l,r;cin>>l>>r;
    int ans=sol(r)-sol(l-1);
    cout<<ans<<endl;
}
signed main(){
    
    
    ios::sync_with_stdio(0);
    init();
    int T;cin>>T;
    while(T--){
    
    
        solve();
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/weixin_44178736/article/details/115239473