题目链接:https://codeforces.com/problemset/problem/55/D
题意:输出 中满足这个数对它自己每一位非零数字都整除的数的个数.
思路:刚开始想了枚举数的集合然后数位 但是实在是太慢了…看了题解才知道我们已知 的最小公倍数是 ,那么我们假设要求数 模 是等于 的,然后我们改写 为 已知 一定整除 所以问题就转化成 是否整除它数位上的每一个非零的数字,定义 表示从高到低考虑前 个数位模 为 ,已经出现的非零的数字集合为 ,当前 是否等于 的情况为 的方案数然后 ,记忆化搜索去掉最后一维去搜索即可,注意到什么数都整除 所以只要考虑 即可.
#include <bits/stdc++.h>
#define MP make_pair
#define PB emplace_back
using namespace std;
typedef long long ll;
template<typename T>
inline T read(T&x){
x=0;int f=0;char ch=getchar();
while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x=f?-x:x;
}
const int P=2520;
int T,status,i,digit[20];
ll l,r,ans,dp[20][256][2520];
ll dfs(int pos,int S,int num,bool jud){
if (!pos){
for (int i=0;i<8;++i)if(S&(1<<i)){
if (num%(i+2)) return 0;
}
return 1;
}
if (!jud && ~dp[pos][S][num]) return dp[pos][S][num];
int limit=jud?digit[pos]:9;
ll ret=0;
for (int i=0;i<=limit;++i){
ret+=dfs(pos-1,i>1?S|(1<<(i-2)):S,(num*10+i)%P,jud && i==limit);
}
if (!jud) dp[pos][S][num]=ret;
return ret;
}
ll cal(ll x){
if (!x) return 1;
int len=0;
while (x){
digit[++len]=x%10;
x/=10;
}
return dfs(len,0,0,1);
}
int main(){
memset(dp,-1,sizeof(dp));
for (read(T);T--;){
read(l),read(r);
printf("%lld\n",cal(r)-cal(l-1));
}
return 0;
}
Written by Yiming Pan who lives and works in Hangzhou China. Welcome follow me on Github
Cannot load comments. Please check you network.