洛谷 P6371 解题记录

Every "END" is a new "BEGINNING"

简单数位 dp。但不知道为什么评了紫。

一开始是以为和 [一本通 5.3 练习 1]数字游戏 2 一样,复制过来代码改了改就准备提交。

测了样例,WA。

然后才发现,我读错题了啊啊!!!题目要求是原数被 $X$ 整除,不是数字和被 $X$ 整除。

简单改了下代码,结果一堆 RE。

啊啊啊数组开小了啊啊!!!

数组开到 $4 \times {10}^8$。

啊啊啊 MLE!!!

仔细看看数据范围。

竟然 $X < {10}^{11}$。

然后发现 $X > {10}^5$ 的时候可以暴力。

简单打了打暴力。

$72$ 分。

忘记特判前导零了啊!

$93$ 分。

前导零可以有多个啊!

AC。

代码:

#include<bits/stdc++.h> 
using namespace std;
long long MOD,ant[15][100005],ant2[15][100005],lg10[15],ans,a,b;
string s;
void init(){
	lg10[0]=1;
	for(int i=1;i<=13;i++)lg10[i]=lg10[i-1]*10;
	ant[0][0]=1;
	for(int i=0;i<s.size();i++)ant[1][(s[i]-48)%MOD]++;
	for(int i=2;i<=11;i++){
		for(int j=0;j<s.size();j++){
			for(int k=0;k<MOD;k++){
				ant[i][((s[j]-48)*lg10[i-1]+k)%MOD]+=ant[i-1][k%MOD];
			}
		}
	}
    ant2[0][0]=1;
    for(int i=1;i<=11;i++){
    for(int j=0;j<MOD;j++)ant2[i][j]=ant[i][j]+ant2[i-1][j];
    }
}

void DEBUG(){
	for(int i=1;i<=11;i++){
		for(int j=0;j<MOD;j++)cout<<ant[i][j]<<" ";
		cout<<endl;
	}
}
void Sol2(){
    for(long long i=MOD;i<=b;i+=MOD){
        bool flag=1;
        long long y=i;
        if(i<a)flag=0;else
        while(y){
            for(int j=0;j<s.size();j++){
                if(s[j]-48==y%10)break;
                if(j==s.size()-1)flag=0;
            }
            y/=10;
        }
        ans+=flag;
    }
    cout<<ans;
    exit(0);
}
int main(){
    cin>>MOD>>a>>b;
    cin>>s;
    if(MOD>100000)Sol2();
		memset(ant,0,sizeof(ant));
		init();
		ans=0;
		int adgt=0,bdgt=0,tot=0;
		b++;
	while(lg10[adgt]<=a)adgt++;
	while(lg10[bdgt]<=b)bdgt++;
	for(int i=bdgt;i>=1;i--){
		int st=b/lg10[i-1];
        if(i==bdgt&&s[0]!=48)ans+=ant2[i-1][0];
		for(int j=0;j<s.size()&&s[j]-48<st;j++){
			ans+=ant[i-1][(MOD*1145141919810-(s[j]-48+tot)*lg10[i-1])%MOD];
        
		}
        bool flag=0;
        for(int j=0;j<s.size();j++){
            if(s[j]-48==st)flag=1;
        }
        if(!flag)break;
		tot+=st;
        tot*=10;
		b%=lg10[i-1];
		if(!b)break;
	}
	tot=0;
	for(int i=adgt;i>=1;i--){
		int st=a/lg10[i-1];
        if(i==adgt&&s[0]!=48)ans-=ant2[i-1][0];
		for(int j=0;j<s.size()&&s[j]-48<st;j++){
			ans-=ant[i-1][(MOD*1145141919810-(s[j]-48+tot)*lg10[i-1])%MOD];
		}
        bool flag=0;
        for(int j=0;j<s.size();j++){
            if(s[j]-48==st)flag=1;
        }
        if(!flag)break;
		tot+=st;
        tot*=10;
		a%=lg10[i-1];
		if(!a)break;
	}
	cout<<ans<<endl;
}
posted @ 2025-04-13 23:56  Phigros_11  阅读(23)  评论(0)    收藏  举报