zoukankan      html  css  js  c++  java
  • [violet2]sillyz

     题意:定义S(n) = n*各数位之积,然后给定L<=R<=10^18,求有多少个n在[L,R]区间内

     思路:

       看了半天无从下手。。看完题解才豁然开朗。。

       具体思路看vani神博客吧。讲的很清楚。。

    code:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 310000;
     5 const ll Inf = 1000000000LL;
     6 int d[maxn], dc[maxn][8], tot;
     7 int td, tc[8];
     8 
     9 void dfs(int r, int s, ll num){
    10      if (num > Inf) return;
    11      if (r == 10 || s == 18){   
    12          d[tot] = num;
    13          for (int i = 0;  i < 8; ++i)
    14               dc[tot][i] = tc[i];
    15          tot++;
    16          return;
    17      }
    18      dfs(r + 1, s, num);
    19      tc[r-2]++;
    20      dfs(r, s + 1, num * r);
    21      tc[r-2]--; 
    22 }
    23 
    24 ll frac[25];
    25 ll count(int m){
    26    int left = m;
    27    ll res = frac[m];
    28    for (int i = 0; i < 8; ++i) left -= tc[i], res /= frac[tc[i]];
    29    res /= frac[left];
    30    return res; 
    31 }
    32 
    33 int bit[20];
    34 
    35 ll calculate(ll b, int p){
    36      if (b <= 1) return 0;
    37      int k = 0;
    38      while (b > 0) bit[++k] = b % 10, b /= 10;
    39      int size = 0;
    40      for (int i = 0; i < 8; ++i)
    41          tc[i] = dc[p][i], size += tc[i];
    42      ll res = 0;
    43      for (int i = 1; i < k; ++i)
    44           if (i >= size) res += count(i);
    45      for ( ;k > 0; --k){
    46           if (bit[k] == 0 || size > k) break;
    47           for (int i = 2; i < bit[k]; ++i) if (tc[i-2]){
    48               --tc[i-2], --size;
    49               if (k > size) res += count(k - 1);
    50               ++tc[i-2], ++size;
    51           }
    52           if (bit[k] >= 2){
    53               if (k > size) res += count(k-1);
    54               if (tc[bit[k]-2] == 0) break;
    55               --tc[bit[k]-2], --size;
    56           }
    57      }
    58      return res;
    59 }
    60 
    61 ll calculate(ll x){
    62    if (x <= 0) return 0;
    63    ll res = 0;
    64    for (int i = 0; i < tot; ++i)
    65         res += calculate(x / d[i] + 1, i);
    66    return res;
    67 }
    68 
    69 void pre_do(){
    70     frac[0] = 1;
    71     for (int i = 1; i <= 18; ++i) frac[i] = frac[i-1] * i;
    72     memset(tc, 0, sizeof(tc));
    73     tot = 0;
    74     dfs(2, 0, 1);
    75 }
    76 
    77 int main(){
    78  //   freopen("a.in", "r", stdin);
    79  //   freopen("a.out", "w", stdout);
    80     pre_do();
    81     ll l, r;
    82     while (cin >> l >> r){
    83          ll ans  = calculate(r) - calculate(l - 1);
    84          cout << ans << endl;
    85     } 
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    CSU1784
    HDU 6128 Inverse of sum(数学)
    容斥原理入门
    HDU 6129 Just do it(规律)
    HDU 6140 Hybrid Crystals(zz)
    HDU 6143 Killer Names(排列+容斥,dp)
    zzuli 2177 Contest
    zzuli 2180 GJJ的日常之沉迷数学(逆元)
    除法逆元入门
    乘法逆元数论篇
  • 原文地址:https://www.cnblogs.com/yzcstc/p/4032054.html
Copyright © 2011-2022 走看看