Hướng dẫn giải của Đếm số


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

Code mẫu của flashmt

const fi='';
      maxl=16;
var a,b:int64;
    d,k,l:longint;
    f,s,f0:array[1..maxl,0..9,-1..maxl] of int64;
    c:array[1..maxl] of longint;

procedure dp;
var i,j,p,q:longint;
begin
     for j:=0 to 9 do f[1,j,0]:=1;
     for i:=2 to maxl do
       for j:=0 to 9 do
         for p:=0 to 9 do
           for q:=0 to i-1 do
             if abs(j-p)<=d then
                 f[i,j,q]:=f[i,j,q]+f[i-1,p,q-1]
             else
                 f[i,j,q]:=f[i,j,q]+f[i-1,p,q];
     f0:=f;
     for i:=2 to maxl do
     begin
          for q:=0 to i-1 do f0[i,0,q]:=0;
          for p:=0 to 9 do
              for q:=0 to i-1 do
                  inc(f0[i,0,q],f0[i-1,p,q]);
     end;
     for i:=1 to maxl do
          for j:=0 to 9 do
              for q:=0 to maxl do
                  s[i,j,q]:=s[i,j,q-1]+f[i,j,q];
end;

function calc(a:int64):int64;
var i,j,kk:longint; st:string; re:int64;
begin
     calc:=1+a; re:=0;
     if a<10 then exit;
     str(a,st); l:=length(st);
     kk:=k;
     for i:=1 to l do c[i]:=ord(st[i])-48;
     for j:=0 to kk do re:=re+f0[l,0,j];
     for j:=1 to c[1]-1 do re:=re+s[l,j,kk];
     for i:=2 to l-1 do
     begin
          for j:=0 to c[i]-1 do
              if abs(j-c[i-1])<=d then re:=re+s[l-i+1,j,kk-1]
              else re:=re+s[l-i+1,j,kk];
          if abs(c[i]-c[i-1])<=d then dec(kk);
          if kk<0 then
          begin
               calc:=re; exit;
          end;
     end;
     if l>1 then
        for j:=0 to c[l] do
            if (abs(j-c[l-1])>d) or (kk>0) then inc(re);
     calc:=re;
end;

begin
     assign(input,fi); reset(input);
     read(a,b,d,k);
     close(input);
     dp;
     writeln(calc(b)-calc(a-1));
end.

Code mẫu của happyboy99x

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

typedef long long int64;
const int L = 20;
int64 f[L][L][10][2];

int lg10(int64 n) {
    int res = 0;
    while(n) n /= 10, ++res;
    return res;
}

int64 calc(int64 n, int64 d, int64 k) {
    if(n < 10) return n;
    memset(f, 0, sizeof f);
    int len = lg10(n);
    k = min(k, len-1LL);
    for(int v = 0; v < 10; ++v)
        for(int diff = 0; diff <= k; ++diff) {
            f[len-1][diff][v][1] = 1;
            f[len-1][diff][v][0] = v == n % 10 ? 1 : 0;
        }
    int64 num = n;
    for(int i = len-2; i >= 0; --i, num /= 10)
        for(int diff = 0; diff <= k; ++diff)
            for(int v = 0; v < 10; ++v) if(i | v)
                for(int s = 0; s < 2; ++s)
                    for(int nx = 0; nx <= (s == 0 ? num % 10 : 9); ++nx)
                        f[i][diff][v][s] += f[i+1][diff + (abs(nx - v) <= d ? 1 : 0)][nx][s | (nx < num % 10 ? 1 : 0)];
    int64 res = 0;
    for(int s = 1; s <= num; ++s)
        res += f[0][0][s][s < num ? 1 : 0];
    return res;
}

int64 beautiful(int64 n, int64 d, int64 k) {
    int64 res = calc(n, d, k);
    for(int64 t = 10; t <= n; t *= 10)
        res += calc(t-1, d, k);
    return res;
}

int main() {
    int64 a, b, d, k;
    cin >> a >> b >> d >> k;
    cout << beautiful(b, d, k) - beautiful(a-1, d, k) << endl;
    return 0;
}

Code mẫu của ladpro98

#include <bits/stdc++.h>
#define long long long
const int N = 25;
using namespace std;
long A, B, D, K;
long F[N][N][N];

long DP(long a) {
    int digit[N], d = 0;
    while (a) {digit[++d] = a % 10; a /= 10;}
    reverse(digit + 1, digit + 1 + d);
    long res = 0;
    for(int i = 1; i < d; i++) for(int j = 0; j <= 9; j++)
        for(int k = 0; k <= K; k++) res += F[i][j][k];
    long C[N][N][N][2];
    memset(C, 0, sizeof C);
    //C[i][j][k][t] = use i digits, last one is j, k bad position to the left,
    //t == 1 if the number if == a up to i
    for(int j = 1; j <= digit[1]; j++) C[1][j][0][j < digit[1] ? 0 : 1] = 1;
    for(int i = 1; i <= d; i++) for(int j = 0; j <= 9; j++)
    for(int k = 0; k <= K; k++) for(int t = 0; t <= 1; t++) {
        if (t == 0) {
            for(int next = 0; next <= 9; next++)
                C[i + 1][next][abs(next - j) <= D ? k + 1 : k][0] += C[i][j][k][0];
        }
        else  {
            for(int next = 0; next <= digit[i + 1]; next++)
                C[i + 1][next][abs(next - j) <= D ? k + 1 : k][next == digit[i + 1] ? 1 : 0] += C[i][j][k][t];
        }
    }
    for(int j = 0; j <= 9; j++) for(int k = 0; k <= K; k++) for(int t = 0; t <= 1; t++)
        res += C[d][j][k][t];
    return res;
}

int main()
{
    scanf("%lld %lld %lld %lld", &A, &B, &D, &K); K = min(K, 15ll);
    //F[i][j][k] = use i digits, the last digit is j, and k bad position to the left
    for(int j = 1; j <= 9; j++) F[1][j][0] = 1;
    for(int i = 0; i <= 15; i++)
    for(int j = 0; j <= 9; j++)
    for(int k = 0; k <= K; k++)
        for(int next = 0; next <= 9; next++)
            if (abs(j - next) <= D) F[i + 1][next][k + 1] += F[i][j][k];
            else F[i + 1][next][k] += F[i][j][k];
    long res = DP(B) - DP(A - 1);
    printf("%lld", res);
    return 0;
}

Code mẫu của RR

{$R+,Q+}
PROGRAM DEMSO;
CONST
  fi='';
  fo='';
TYPE
  so=array[0..16] of integer;
VAR
  a,b:so;
  d,k:integer;
  f:array[1..16,0..16,0..9,0..2] of int64;
procedure readInput;
var
  f:text;
  ch:string[1];
  code:shortint;
begin
  assign(f,fi); reset(f);
  repeat
    read(f,ch);
    if ch<>' ' then begin inc(a[0]); val(ch,a[a[0]],code); end;
  until ch=' ';
  repeat
    read(f,ch);
    if ch<>' ' then begin inc(b[0]); val(ch,b[b[0]],code); end;
  until ch=' ';
  readln(f,d,k);
  close(f);
end;
function cal(a:so):int64;
var
  s,x,c,cc,tt:integer;
  kq:int64=0;
begin
  fillchar(f,sizeof(f),0);
  for c:=0 to 9 do
    if a[1]>c then f[1,0,c,0]:=1
    else if a[1]=c then f[1,0,c,1]:=1
    else f[1,0,c,2]:=1;
  for s:=2 to a[0] do
  for x:=0 to k do
  for c:=0 to 9 do
    for cc:=0 to 9 do
    if (s>2) or (cc>0) then
      begin
        if abs(cc-c)>d then f[s,x,c,0]:=f[s,x,c,0]+f[s-1,x,cc,0]
        else if x>0 then f[s,x,c,0]:=f[s,x,c,0]+f[s-1,x-1,cc,0];
        if c<a[s] then
          if abs(cc-c)>d then f[s,x,c,0]:=f[s,x,c,0]+f[s-1,x,cc,1]
          else if x>0 then f[s,x,c,0]:=f[s,x,c,0]+f[s-1,x-1,cc,1];
        if c=a[s] then
          if abs(cc-c)>d then f[s,x,c,1]:=f[s,x,c,1]+f[s-1,x,cc,1]
          else if x>0 then f[s,x,c,1]:=f[s,x,c,1]+f[s-1,x-1,cc,1];
        if abs(cc-c)>d then f[s,x,c,2]:=f[s,x,c,2]+f[s-1,x,cc,2]
        else if x>0 then f[s,x,c,2]:=f[s,x,c,2]+f[s-1,x-1,cc,2];
        if c>a[s] then
          if abs(cc-c)>d then f[s,x,c,2]:=f[s,x,c,2]+f[s-1,x,cc,1]
          else if x>0 then f[s,x,c,2]:=f[s,x,c,2]+f[s-1,x-1,cc,1];
      end;
  for s:=1 to a[0]-1 do
  for x:=0 to k do
  for c:=0 to 9 do
  for tt:=0 to 2 do
    kq:=kq+f[s,x,c,tt];
  for x:=0 to k do
  for c:=0 to 9 do
    kq:=kq+f[a[0],x,c,0];
  cal:=kq;
end;
function ok(a:so):integer;
var
  i,count:integer;
begin
  count:=0;
  for i:=1 to a[0]-1 do
    if abs(a[i]-a[i+1])<=d then inc(count);
  if count<=k then ok:=1 else ok:=0;
end;
procedure writeOutput;
var
  f:text;
begin
  assign(f,fo); rewrite(f);
  writeln(f,cal(b)-cal(a)+ok(b));
  close(f);
end;
BEGIN
  readInput;
  writeOutput;
END.

Code mẫu của hieult

#include <cstdio>
//#include <conio.h>
#include <math.h>

    long long A,B,F[20][20][20];
    int d,K;

long long TTD(long long x)
{
     if (x<0) return -x;
     return x;
}

long long xuly(long long x)
{
     int a[20],b[20],t=0;
     long long the=x,KQ=0;
     while(the!=0)
     {
         b[++t]=the%10;
         the = the/10;
     }
     for(int i = 1;i<=t;i++) a[i] = b[t+1-i];
     for(int i = 1;i<t;i++)
         for(int j = 1;j<=9;j++)
             for(int k = 0;k<=K;k++)
                 KQ = KQ+F[i][j][k];
               //  printf("%d\n",KQ);
     int KK = K;
     for(int i = 1;i<=t;i++)
     {
         if(i>2 && TTD(a[i-1]-a[i-2])<=d)
             KK--;
         if(KK<0) {break;}
         int KKK;
         if(i==1)
         {
         for(int j = 1;j<a[i];j++)
              for(int k = 0;k<=KK;k++)
                   KQ = KQ+ F[t+1-i][j][k];
         }
         else
         {
         for(int j = 0;j<a[i];j++)
              {
              if(TTD(a[i-1]-j)<=d)
                  KKK = KK-1;
              else KKK = KK;
              for(int k = 0;k<=KKK;k++)
                   KQ = KQ+ F[t+1-i][j][k];
              }
         }
     }
     return KQ;
}

bool check(long long x)
{
     int a[20],b[20],t=0,so=0;
     long long the=x,KQ=0;
     while(the!=0)
     {
         b[++t]=the%10;
         the = the/10;
     }
     for(int i = 1;i<=t-1;i++)
         if(TTD(b[i+1]-b[i])<=d)
             so++;
     if(so>K)
          return false;
     else return true;
}
int main()
{

    //printf("*** %lld\n",F[2][1][0]);

    scanf("%lld %lld %d %d",&A,&B,&d,&K);
    for(int i = 0;i<=9;i++)
        F[1][i][0] = 1;
    for(int i =0;i<=9;i++)
         for(int j = 1;j<=15;j++)
              F[1][i][j] = 0;
    for(int i = 2;i<=15;i++)
         for(int j = 0;j<=9;j++)
              for(int k = 0;k<=15;k++)
              {
                  F[i][j][k]=0;
                  for(int u = 0;u<=9;u++)
                  {
                      if(TTD(j-u)>d)
                          F[i][j][k]+= F[i-1][u][k];
                      else if(k>0)F[i][j][k]+= F[i-1][u][k-1];
                     // if(i==2 && j==1 &&k==0)
                       //   printf("%d %d\n",u,F[i][j][k]);
                  }
              }
    if(!check(B))
    printf("%lld",xuly(B)-xuly(A));
    else printf("%lld",xuly(B)-xuly(A)+1);
   // int sa = 0;
    //for(int i = A;i<=B;i++)
     //   if(check(i))
     //  ++sa;
   // printf("\n%d",sa); 
    //getch();
}

Code mẫu của skyvn97

#include<cstdio>
#include<cstring>
typedef long long ll;
struct num {
    int nd;
    int d[20];
    num() {
        nd=0;
    }
    num(ll x) {
        nd=0;
        while (x>0) {
            nd++;
            d[nd-1]=x%10;
            x=x/10;
        }
    }
    int operator [] (const int &i) const {
        return (d[i]);
    }
};
ll num9[20];
ll f[20][13][20][3];
ll a,b;
int d,k;
int abs(const int &x) {
    if (x<0) return (-x); else return (x);
}
void init(void) {
    int i;
    num9[1]=9;
    for (i=2;i<=17;i=i+1) num9[i]=(num9[i-1]+1)*10-1;
}
ll count(const ll &x,int m) {
    if (x<1) return (0);
    num tmp=num(x);
    int n=tmp.nd;
    //printf("%d\n",n);
    if (m>=n) m=n-1;
    int i,j,k,l,t;
    for (i=1;i<17;i=i+1)
        for (j=0;j<10;j=j+1)
            for (k=0;k<17;k=k+1)
                for (l=0;l<2;l=l+1)
                    f[i][j][k][l]=0;
    for (i=1;i<=tmp[n-1];i=i+1) f[1][i][0][i<tmp[n-1]]=1;
    for (i=1;i<n;i=i+1)
        for (j=0;j<10;j=j+1)
            for (k=0;k<i && k<=m;k=k+1)
                for (l=0;l<2;l=l+1)
                    for (t=0;t<=(1-l)*tmp[n-i-1]+9*l;t=t+1) {
                        f[i+1][t][k+(abs(t-j)<=d)][l||(t<tmp[n-i-1])]+=f[i][j][k][l];
                        //printf("Updated f(%d,%d,%d,%d)=%lld to f(%d,%d,%d,%d)\n",i,j,k,l,f[i][j][k][l],i+1,t,k+(abs(t-j)<=d),l||(t<tmp[n-i-1]));
                    }
    ll res=0;
    for (j=0;j<10;j=j+1)
        for (k=0;k<=m;k=k+1)
            res+=f[n][j][k][1]+f[n][j][k][0];
    //printf("Result is %lld\n",res);
    return (res);
}
ll count(const ll &x) {
    int i;
    if (x<1) return (0);
    //printf("Count %lld\n",x);
    int n=num(x).nd;
    ll res=0;
    for (i=1;i<n;i=i+1) {
        res+=count(num9[i],k);
        //printf("%lld\n",res);
    }
    res+=count(x,k);
    return (res);
}
void process(void) {
    scanf("%lld",&a);
    scanf("%lld",&b);
    scanf("%d",&d);
    scanf("%d",&k);
    printf("%lld",count(b)-count(a-1));
}
int main(void) {
    init();
    process();
    return 0;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.