zoukankan      html  css  js  c++  java
  • 洛谷 P2602 [ZJOI2010]数字计数

    洛谷

    第一次找规律A了一道紫题,写篇博客纪念一下。

    这题很明显是数位dp,但是身为蒟蒻我不会呀,于是就像分块打表水过去。

    数据范围是(10^{12}),我就(10^6)一百万一百万的打表。

    于是我就发现了一些规律。

    先献给大家一个打表程序吧~

    #include <bits/stdc++.h>
    using namespace std;
    
    int main()
    {
        long long l,r,cnt[10]={};
        for (long long t=0;t<=999999;++t) {
            l=t*1000000+1;
            r=(t+1)*1000000;
            for (long long i=l;i<=r;++i) {
                long long n=i;
                while (n) ++cnt[n%10],n/=10;
            }
            for (long long i=0;i<=9;++i) cout<<cnt[i]<<' ';
            cout<<endl;
        }
        return 0;
    }
    

    这是1~1000000,1000001~2000000,2000001~3000000……的表。

    也看一下吧。

    488895 600001 600000 600000 600000 600000 600000 600000 600000 600000 
    1088895 2200000 1200001 1200000 1200000 1200000 1200000 1200000 1200000 1200000 
    1688895 2800000 2800000 1800001 1800000 1800000 1800000 1800000 1800000 1800000 
    2288895 3400000 3400000 3400000 2400001 2400000 2400000 2400000 2400000 2400000 
    2888895 4000000 4000000 4000000 4000000 3000001 3000000 3000000 3000000 3000000 
    3488895 4600000 4600000 4600000 4600000 4600000 3600001 3600000 3600000 3600000 
    4088895 5200000 5200000 5200000 5200000 5200000 5200000 4200001 4200000 4200000 
    4688895 5800000 5800000 5800000 5800000 5800000 5800000 5800000 4800001 4800000 
    5288895 6400000 6400000 6400000 6400000 6400000 6400000 6400000 6400000 5400001 
    5888896 7000001 7000000 7000000 7000000 7000000 7000000 7000000 7000000 7000000 
    7488895 8600002 7600000 7600000 7600000 7600000 7600000 7600000 7600000 7600000 
    8088895 11200001 8200001 8200000 8200000 8200000 8200000 8200000 8200000 8200000 
    8688895 12800001 9800000 8800001 8800000 8800000 8800000 8800000 8800000 8800000
    

    这时候你会发现两个规律:

    • 每隔一百万,各个数字都会增加600000个,很神奇。
    • 对于当前的数字i,如果(frac{i}{10^k}>0(5<k<13)),那么(cnt[(frac{i}{10^k})~ exttt{mod}~10]+=1000000)

    有了这两大规律,我们就可以轻松处理出(10^{12})的大数据了。

    复杂度约为(O(frac{r-l+1}{1000000}))

    代码在下面:

    #include <bits/stdc++.h>
    using namespace std;
    int main()
    {
        long long a[10]={};
        long long l,r;cin>>l>>r;
        while (l<r&&l%1000000) {
            long long t=l;
            while (t) ++a[t%10],t/=10;
            ++l;
        }
        while (r>l&&r%1000000) {
            long long t=r;
            while (t) ++a[t%10],t/=10;
            --r;
        }
        while (l!=r) {
            for (int i=0;i<10;++i)
                a[i]+=600000;
            long long t=1000000;
            while (l/t&&t<=1000000000000) {
                a[l/t%10]+=1000000;
                t*=10;
            }
            l+=1000000;
        }
        while (r) ++a[r%10],r/=10;
        for (int i=0;i<10;++i) cout<<a[i]<<' ';
        return 0;
    }
    
  • 相关阅读:
    获取本机IP,用户代理
    10 种机器学习算法的要点(附 Python)(转载)
    怎么查找执行比较慢的sql语句-DBA给的建议
    .net 调度器怎么实现心跳(socket除了他,没选择吧)
    分布式多计算机调度平台
    续【C# 以管理员方式启动Winform,进而使用管理员控制Windows Service】
    C# 以管理员方式启动Winform,进而使用管理员控制Windows Service
    SqlServer2008根据现有表,获取该表的分区创建脚本
    SqlServer常用命令
    创建分区表过程
  • 原文地址:https://www.cnblogs.com/fushao2yyj/p/9582344.html
Copyright © 2011-2022 走看看