洛谷P6371题解
本文同步更新于洛谷博客
题目描述
使用给定的数字,组成一些在 之间的数使得这些数每个都能被 整除。
题解
对于 ,我们可以直接枚举 的倍数,然后判断其是否符合条件。
对于 ,则使用数位 dp。我们传四个参数 进入 dfs,分别表示第 位,模 的余数为 ,这一位填的数有没有限制以及是否为前导 ,用 数组记忆化即可。
注意
要区分前导 和题目中给定的 。
Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+5;
int len,a[15];
ll p,l,r,f[15][maxn];
bool vis[15];
char s[15];
ll dfs(int k,int s,int t,int u)
{
if(!k)
return s?0:1;
if(!t&&!u&&f[k][s]!=-1)
return f[k][s];
int x=t?a[k]:9;
ll res=0;
if(u)
res+=dfs(k-1,0,t&&!x,1);
for(int i=0;i<=x;i++)
{
if(vis[i])
{
if(u&&!i)
continue;
res+=dfs(k-1,(s*10+i)%p,t&&(i==x),0);
}
}
if(!t&&!u)
f[k][s]=res;
return res;
}
ll divide(ll x)
{
len=0;
while(x)
{
a[++len]=x%10;
x/=10;
}
return dfs(len,0,1,1);
}
bool check(ll x)
{
while(x)
{
if(!vis[x%10])
return 0;
x/=10;
}
return 1;
}
int main()
{
memset(f,-1,sizeof(f));
scanf("%lld%lld%lld\n%s",&p,&l,&r,s+1);
for(int i=1;s[i];i++)
vis[s[i]-'0']=1;
if(p<maxn)
printf("%lld\n",divide(r)-divide(l-1));
else
{
ll tmp=l%p?l/p+1:l/p,ans=0;
for(ll i=tmp*p;i<=r;i+=p)
ans+=check(i);
printf("%lld\n",ans);
}
return 0;
}
本文作者:Ginger_he
本文链接:https://www.cnblogs.com/Gingerhe/p/16056907.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步