Cod sursa(job #3140075)

Utilizator RolandPetreanPetrean Roland RolandPetrean Data 3 iulie 2023 18:20:19
Problema Cifre Scor 30
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 1.58 kb
// https://www.infoarena.ro/problema/cifre
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'

ifstream fin("cifre.in");
ofstream fout("cifre.out");

const int EQ = 0, LT = 1;

int k, c;

int _solve(vector<int> v) {
  int n=v.size()-1;

  // dp[i][j][EQ / LT]
  //    - numerele de i cifre mai mici ca v care au j cifre egale cu c
  //    - EQ = numarul e egal cu v[0..i]
  //    - LT = numarul e mai mic ca v[0..i]

  vector<vector<vector<int>>> dp(n+1, vector<vector<int>>(n+1, vector<int>(2)));
  dp[0][0][EQ] = 1;

  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j <= n; ++j) {
      if (j && v[i] == c) dp[i][j][EQ] += dp[i-1][j-1][EQ];
      else if (v[i] != c) dp[i][j][EQ] += dp[i-1][j][EQ];

      dp[i][j][LT] += dp[i-1][j][EQ] * (v[i]-1);
      dp[i][j][LT] += dp[i-1][j][LT] * 10;
      if (j) {
        if (v[i] > c) dp[i][j][LT] += dp[i-1][j-1][EQ];
        dp[i][j][LT] += dp[i-1][j-1][LT];
      }
    }
  }

  int ans = 0;
  for (int j = k; j <= n; ++j) ans += dp[n][j][EQ] + dp[n][j][LT];
  return ans;
}
int solve(vector<int> v) {
  auto all9 = v;
  for (int& x:all9) x = 9;

  int ans = 0;
  while (all9.size()>1) {
    all9.pop_back();
    ans += _solve(all9);
  }

  return ans + _solve(v);
}

vector<int> digits(int n) {
  vector<int> d;
  do {
    d.push_back(n%10);
    n /= 10;
  } while (n);
  d.push_back(-1);
  reverse(d.begin(), d.end());
  return d;
}
int main() {
  
  int a, b;
  fin>>a>>b>>c>>k;

  auto da1 = digits(a-1), db = digits(b);

  int cnt = solve(db) - (a ? solve(da1) : 0);
  double ans = (double) cnt / (b-a+1);

  fout<<fixed<<setprecision(4)<<ans;
}