CF628D Magic Numbers

Title Description

Give you two numbers m and d

Give you two numbers L , r

Interrogation interval [l, r] are satisfied even bit number is the number of d and d is not odd bit number (bits from the left) is a multiple of m

1 <=m <= 2000 , 0 <= d <=9

l <= r <= 10 ^ 2000

To ensure that a <= b and a and b are the same number of bits

answer

A start has been considered the leading zero, discuss thief trouble, look after the problem solution found did not consider leading zeros, a look at the English title only to find the same number of digits. There can not be a bit odd d do not know. (Or learn good English)

Then it is simple, direct f [s] [sum] s-enumeration current position, the current number mod m = sum

Read a character, so l directly special sentenced to facilitate that, but if l-1, then the number of bits less likely to go wrong.

#include<bits/stdc++.h>
using namespace std;

const int mod=1000000007;
const int maxn=2005;
int m,d;
int len,num[maxn];
int f[maxn][maxn];
char l[maxn],r[maxn];

int dfs(int s,int sum,int lim){
    if(!s) return !sum;
    if(!lim&&f[s][sum]!=-1) return f[s][sum];
    int mx= lim ? num[s] : 9 ;
    int ret=0;
    for(int i=0;i<=mx;i++){
        if((len-s)&1) {if(i!=d) continue;}
        else if(i==d) continue;
        ret=(ret+dfs(s-1,(sum*10+i)%m,lim&&i==mx))%mod;
    }
    if(!lim) f[s][sum]=ret;
    return ret;
}

bool check(){
    int x=0;
    for(int i=len;i;i--){
        if((len-i)&1){if(num[i]!=d) return false;}
        else if(num[i]==d) return false;
        x=(x*10+num[i])%m;
    }
    return !x;
}

int cx(){
    memset(f,-1,sizeof(f));
    len=strlen(r+1);
    for(int i=1;i<=len;i++) num[i]=r[len-i+1]-'0';
    int temp2=dfs(len,0,true);
    len=strlen(l+1);
    for(int i=1;i<=len;i++) num[i]=l[len-i+1]-'0';
    int temp1=dfs(len,0,true);
    int ans=temp2-temp1;
    ans+=check();
    return ans;
}

int main(){
    scanf("%d%d",&m,&d);
    scanf("%s%s",l+1,r+1);
    printf("%d",(cx()%mod+mod)%mod);
}
View Code

If the number is not the same, then it should open two dimensions: whether the current position is odd, whether with leading zeros.

Consider only whether the record is a bit odd transfer is correct, if the memory of the first words of the current position and the sum must be the same, so as

00xxxx...

0000xx...

If there is a first-fill method, just follow the second filling enough.

This question is okay, because d is not filled to the first bit so I do not need to consider d = 0. So if direct bit is even filled d; otherwise it is an enumeration, can not take d, if there is no leading zeros or is this a Motian 0 then the parity-digit next bit will change, otherwise unchanged.

#include<bits/stdc++.h>
using namespace std;

const int mod=1000000007;
const int maxn=2005;
int m,d;
int len,num[maxn];
int f[maxn][maxn][2][2];
char l[maxn],r[maxn];

int dfs(int s,int sum,int lim,bool even,bool qdl){
    if(!s) return !sum&&!qdl;
    if(!lim&&f[s][sum][even][qdl]!=-1) return f[s][sum][even][qdl];
    int mx= lim ? num[s] : 9 ;
    int ret=0;
    if(!even){
        if(lim&&mx<d) return 0;
        ret=dfs(s-1,(sum*10+d)%m,lim&&d==mx,!even,false);
        if(!lim) f[s][sum][even][qdl]=ret;
        return ret;
    }
    for(int i=0;i<=mx;i++){
        if(i==d) continue;
        if(qdl&&!i) ret=(ret+dfs(s-1,sum*10%m,lim&&i==mx,even,true))%mod;
        else ret=(ret+dfs(s-1,(sum*10+i)%m,lim&&i==mx,!even,false))%mod;
    }
    if(!lim) f[s][sum][even][qdl]=ret;
    return ret;
}

bool check(){
    int x=0;
    for(int i=len;i;i--){
        if((len-i)&1){if(num[i]!=d) return false;}
        else if(num[i]==d) return false;
        x=(x*10+num[i])%m;
    }
    return !x;
}

int cx(){
    memset(f,-1,sizeof(f));
    len=strlen(r+1);
    for(int i=1;i<=len;i++) num[i]=r[len-i+1]-'0';
    int temp2=dfs(len,0,true,true,true);
    len=strlen(l+1);
    for(int i=1;i<=len;i++) num[i]=l[len-i+1]-'0';
    int temp1=dfs(len,0,true,true,true);
    int ans=temp2-temp1;
    ans+=check();
    return ans;
}

int main(){
    scanf("%d%d",&m,&d);
    scanf("%s%s",l+1,r+1);
    printf("%d",(cx()%mod+mod)%mod);
}
View Code

0 There Laid full sentence, or when l = 1 0 if legitimate, when d = 0, from 0 rdfs not legitimate.

Write code r- (l-1), but does not know why he hung up, because it seems to get more answers from l-1.

#include<bits/stdc++.h>
using namespace std;

const int mod=1000000007;
const int maxn=2005;
int m,d;
int len,num[maxn];
int f[maxn][maxn][2][2];
char l[maxn],r[maxn];

int dfs(int s,int sum,int lim,bool even,bool qdl){
    if(!s) return !sum&&!qdl;
    if(!lim&&f[s][sum][even][qdl]!=-1) return f[s][sum][even][qdl];
    int mx= lim ? num[s] : 9 ;
    int ret=0;
    if(!even){
        if(lim&&mx<d) return 0;
        ret=dfs(s-1,(sum*10+d)%m,lim&&d==mx,!even,false);
        if(!lim) f[s][sum][even][qdl]=ret;
        return ret;
    }
    for(int i=0;i<=mx;i++){
        if(i==d) continue;
        if(qdl&&!i) ret=(ret+dfs(s-1,sum*10%m,lim&&i==mx,even,true))%mod;
        else ret=(ret+dfs(s-1,(sum*10+i)%m,lim&&i==mx,!even,false))%mod;
    }
    if(!lim) f[s][sum][even][qdl]=ret;
    return ret;
}

int cx(){
    memset(f,-1,sizeof(f));
    len=strlen(r+1);
    for(int i=1;i<=len;i++) num[i]=r[len-i+1]-'0';
    int temp2=dfs(len,0,true,true,true);
    memset(f,-1,sizeof(f));
    len=strlen(l+1);
    for(int i=1;i<=len;i++) num[i]=l[len-i+1]-'0';
    num[1]--;
    for(int i=1;i<=len;i++){
        if(num[i]>=0)break;
        num[i]+=10;
        num[i+1]--;
    }
    if(!num[len]) len--;
    int temp1=dfs(len,0,true,true,true);
    int ans=temp2-temp1;
    return ans;
}

int main(){
    scanf("%d%d",&m,&d);
    scanf("%s%s",l+1,r+1);
    printf("%d",(cx()%mod+mod)%mod);
}
moment

 Does anyone know help me (orz)

Guess you like

Origin www.cnblogs.com/sto324/p/11402113.html