• Codeforces


    题目链接
    题目大意:给你一个数字(n),问你在(000...000)(999...999)((10^{n-1})位)里面长度为(1,2...n)里的块有多少(相等的连续子段算一块)。
      我们可以尝试构造出长度为i的块,对于一个长度为i的块来说:
      1.若它在数字的边缘,那么它右边(或左边)的第一个数一定与块内的数不同,又因为这个块可以在左边缘也可以在右边缘,所以这(i+1)个数一共有(10 imes 9 imes 2)种情况,而剩下的部分有(n-i-1)位,所以就有(10^{n-i-1})种情况。所以一共是(10 imes 9 imes 2 imes 10^{n-i-1})种情况。
      2.若他不在数字的边缘,那么它的左右两边都有不同的数字,所以这(i+2)这个数就有(10 imes 9 imes 9)种情况,而剩下的部分有(n-i-2)位,所以就有(10^{n-i-2})种情况。但是还没完,这个块还可以平移,每次平移一位,我们的情况数就会增加,因为我们的一个块带上两边一共有(i+2)的长度,所以一共可以平移(n-(i+2))次,再算上本身的这一次,一共是(10 imes 9 imes 9 imes 10^{n-i-2} imes (n-(i+2)+1))种情况。
      关于会不会算多或者算少的问题,我们每次算的只是所有数中长度为(i)的一部分,这些部分累加起来才是一个完整的数,所以不存在一个完整的数被多次计算的情况,也不会有一个完整的数没有被完全计算的情况。

    const int maxn = 2e5+10;
    ll ans[maxn];
    ll qpow(ll x, int y) {
        ll res = x%MOD, ans = 1;
        while(y) {
            if (y&1) ans = ans*res%MOD;
            res = res*res%MOD;
            y >>= 1;
        }
        return ans%MOD;
    }
    int main(void) {
        ll n;
        scanf("%lld", &n);
        ans[n] = 10, ans[n-1] = 180;
        for (ll i = 1; i<=n-2; ++i)
            ans[i] = (ans[i] + 10LL*9*2*qpow(10, n-i-1)%MOD + 10LL*9*9*(n-i-1)%MOD*qpow(10, n-i-2))%MOD;
        for (int i = 1; i<=n; ++i)
            printf(i==n ? "%lld
    " : "%lld ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    IIS: 必须输入密码手动设置密码同步后
    IIS操作控制类
    SQL对IP地址进行拆分
    HTTP_REFERER的工作方式[转贴]
    如何知道同服务器上都有哪些网站?
    简单判断临时表是否存在
    .NET 3.5 SP 1发布了
    Log Parser很好很强大的IIS日志分析工具
    遍历Request.ServerVariables
    06复杂查询(多数据库表)
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12567270.html
Copyright © 2020-2023  润新知