• Codeforces


    题意: 

      在给定范围内(9*10^18)求出有多少个数满足被所有非零位的数整除。

    思路:

      可以先想到如果被所有非零位的数整除,那么就会被他们的lcm整除。

      而lcm(1,2...9) = 2520.

      即2520可以整除1 - 9中任意组合的lcm。

      所以可以用%2520的值表示状态,最后用最终状态值%lcm(x1...xn),判断是否为0。

      1 - 9lcm组合的情况数由 2^3*3^2*5*7可以得出为:4*3*2*2 = 48 ,预处理提取出来。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MOD = 2520;
    int t;
    int bit[20], index[MOD+5];
    ll l, r;
    ll dp[20][MOD][50];
    int gcd(int x, int y) {
        return y==0?x:gcd(y, x%y);
    }
    int lcm(int x, int y) {
        return x/gcd(x, y)*y;
    }
    void init() {
        int cnt = 0;
        memset(dp, -1, sizeof(dp));
        for(int i = 1; i <= MOD; i++)
        if(!(MOD % i)) index[i] = cnt++; 
    }
    ll dfs(int pos, int presum, int prelcm, bool limit) {
        if(pos == -1) return presum%prelcm==0;
        if((!limit) && dp[pos][presum][index[prelcm]] != -1) 
            return dp[pos][presum][index[prelcm]];
        int up = limit?bit[pos]:9;
        ll res = 0;
        for(int i = 0; i <= up; i++) {
            int nowsum = (presum*10+i)%MOD;
            int nowlcm = i==0?prelcm:lcm(prelcm, i);
            res += dfs(pos-1, nowsum, nowlcm, limit && i == bit[pos]);
        } 
        if(!limit) dp[pos][presum][index[prelcm]] = res;
        return res;
    }
    ll solve(ll x) {
        int pos = 0;
        while(x) {
            bit[pos++] = x%10;
            x /= 10; 
        }
        return dfs(pos-1, 0, 1, true);
    }
    int main() {
        init();
        scanf("%d", &t);
        while(t--) {
            scanf("%I64d%I64d", &l, &r);
            printf("%I64d
    ", solve(r) - solve(l-1));
        }
    }
    View Code
  • 相关阅读:
    计算器
    安卓第四周作业
    安卓第三次作业
    补10.21
    补:10.21
    增删改查
    android-數據庫
    安卓 -登陆界面
    android 第Ⅱ次作业
    第一个java代码
  • 原文地址:https://www.cnblogs.com/Pneuis/p/8040591.html
Copyright © 2020-2023  润新知