6361. [2019.9.18] pomfret number of analog NOIP2019

topic

Subject to the effect

Give you an interval \ ([L, R & lt] \) , the demand on each decimal integer in the range from high to low and on the number of reverse.


Reflections on History

A beginning that this is the number of bits DP ......
result has not transferred out of the mentality of collapse ......


Correct

First talk about my SB practices.
First set \ (f_i \) represents the pressing of \ (i \) bit (from low to high, from \ (0 \) contribution to the start).
So is this shift:

  1. Calculation \ (i \) bits contributions. This is a contribution may be a bit difficult to calculate, so I preprocessing a \ (h_ {i, j, 0/1} \) indicates whether pressing \ (i \) bit, \ (0 \) to \ (i \) bits (j \) \ contributions ( \ (J \) is \ (i \) a bit after the \ ([0,9] \) number between). So this thing is \ (h_ {i, a_i} \)
  2. From \ (i-1 \) bits transferred from, where \ (i-1 \) bit is pressing. Apparently \ (I-F_ {}. 1 \) .
  3. From \ (i-1 \) bits transferred from, where \ (i-1 \) bit is not pressing. This is an enumeration select \ (X \) , the contribution is \ (\ sum_ {x = 0 } ^ {a_ {i-1} -1} | x <j | * 10 ^ {i-1} + g_ { +} 2-I (I-. 1) * 10 ^ {2} I-X \) . \ (G_i \) represents \ (0 \) bits to \ (I \) Number of bits of any selected program. This equation can be simplified, not playing out here.

Consider \ (g \) how transfer, the transfer is clearly coming from the front and add this one contribution.
I.e. \ (g_i = 10 * g_ { i-1} + \ frac {(0 + 9) * 10} {2} i * 10 ^ i \)

Then consider \ (h \) transfer.
\ (H_ {I, J, J = 0} * 10 + 10 * ^ H_ {I-I. 1, J, 0} \)
\ (H_ {I, J,. 1} \) transferring relatively complex. And \ (f \) transfer is somewhat similar.
Note \ (NUM \) is \ (0 \) to \ (i-1 \) bit decimal form, i.e. the entire digital to analog \ (I 10 ^ \) .
\ (h_ {i, j, 1} = | a_i <j | * (num + 1) + h_ {i-1, j, 1} + (\ sum_ {x = 0} ^ {a_ {i-1} -1} | x <j | *
10 ^ {i-1} + h_ {i-2, j, 0}) \) also can simplify it.

After simplification, it is easy to find the time complexity of this transfer is \ (O (10n) \) is.

In addition there might be simpler to more advanced practices:
from high to low enumerate a \ (i \) , represents \ (i \) bit pressing cap, and then note the time of contribution.
So there are three contributions:

  1. Higher than \ (i \) bits and \ (i \) contribution. Because of \ (I \) is pressing the upper limit, so the number of figures that can appear in front of all can be recorded with a bucket.
  2. \ (i \) position and below \ (i \) contribution bits. We force behind an upper limit is not pressing, because that digit program will be pressing the cap back to back calculation. Enumeration one back, back then you can pick any.
  3. Higher than \ (i \) position and below \ (i \) contribution bits. This calculation also keep up with a similar.

Then gone.


Code

This problem is too disgusting ...... details Cheetos very ......

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
#define mo 998244353
#define LEN 500010
#define ll long long
char str[LEN];
int n,m,L[LEN],R[LEN];
inline void read(int a[],int &n){
    scanf("%s",str);
    n=strlen(str);
    for (int i=0;i<n;++i)
        a[i]=str[n-i-1]-'0';
    a[n]=0;
}
ll _pow10[LEN],*pow10=_pow10+1;
ll f[LEN],g[LEN],h[LEN][10][2];
inline ll get(int a[],int n){
    if (n<=0)
        return 0;
    g[0]=0;
    for (int i=1;i<=n;++i)
        g[i]=(g[i-1]*10+45*i*pow10[i-1])%mo;
    for (int j=0;j<=9;++j)
        h[0][j][0]=j,h[0][j][1]=(a[0]<j);
    for (int i=1,num=a[0];i<=n;num=(num+pow10[i]*a[i])%mo,++i)
        for (int j=0;j<=9;++j){
            h[i][j][0]=(h[i-1][j][0]*10+j*pow10[i])%mo;
            int tmp=min(a[i-1],j);
            h[i][j][1]=((a[i]<j?num+1:0)+h[i-1][j][1]+(i-2>=0?h[i-2][j][0]*a[i-1]:0)+tmp*pow10[i-1])%mo;
        }
    f[0]=0,f[1]=min(a[0]+1,a[1]);
    for (int i=2;i<=n;++i)
        f[i]=(h[i][a[i]][1]+f[i-1]+a[i-1]*g[i-2]+(i-1)*pow10[i-2]*((a[i-1]-1)*a[i-1]>>1))%mo;
    return f[n];
}
int main(){
    freopen("pair.in","r",stdin);
    freopen("pair.out","w",stdout);
    pow10[0]=1;
    for (int i=1;i<=500001;++i)
        pow10[i]=pow10[i-1]*10%mo;
    int T,ty;
    scanf("%d%d",&T,&ty);
    while (T--){
        read(L,n),read(R,m);
        L[0]--;
        for (int i=0;L[i]<0;++i)
            L[i+1]--,L[i]+=10;
        if (!L[n-1])
            n--;
        printf("%lld\n",(get(R,m)-get(L,n)+mo)%mo);
    }
    return 0;
}

to sum up

In fact, this problem is not difficult thinking ......
but the process is too tired ......

Guess you like

Origin www.cnblogs.com/jz-597/p/11579009.html