zoukankan      html  css  js  c++  java
  • Count The Blocks

    Count The Blocks

    Count The Blocks 题目链接

    思路

    首先打表出来,发现了一个规律 (num[1] = 10, num[2] = 180),这里的数组标记是反的

    发现假定前 (n - 1)个num已经求得,我们可以得到

    (num[n] = n * 10^{n} - sum limits ^{n - 1} _{i = 1}(num[n - i] * (i + 1)))

    通过对上面的带入,我们可以求得 (num[3] = 3000 - (num[2] * 2 + num[1] * 3) = 2610)

    于是我们貌似得到了一个(O(n^2))的算法,想想能不能优化。

    我们定义一个sum变量,其中记录的是(sum limits ^{n - 1} _{i = 1} num[i] * (n - i))

    再开一个前缀和数组,(a[i] = sumlimits ^{i} _{k = 1}num[k]),接下来我们每次的操作就可以变成线性的来更新sum变量,也就是(sum limits ^{n - 1} _{i = 1}(num[n - i] * (i + 1)))一坨东西。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int mod = 998244353;
    const int N = 2e5 + 10;
    
    ll num[N], a[N];
    
    ll quick_pow(ll x, ll n) {
        ll ans = 1;
        while(n) {
            if(n & 1)   ans = (ans * x) % mod;
            n >>= 1;
            x = (x * x) % mod;
        }
        return ans;
    }
    int main() {
        int n;
        scanf("%d", &n);
        num[1] = 10; a[1] = 10;
        ll sum = 10;
        for(int i = 2; i <= n; i++) {
            sum += a[i - 1];
            num[i] = (((quick_pow(10, i) * i) % mod - sum ) % mod + mod) % mod;
            a[i] = (a[i - 1] + num[i]) % mod;
            sum = (sum + num[i]) % mod;
        }
        for(int i = n; i > 0; i--)
            printf("%lld ", num[i]);
        puts("");
        return 0;
    }
    
  • 相关阅读:
    小G的城堡
    最大公约数与扩展欧几里得算法
    阶乘的逆元
    素数的判断
    快速幂
    重载高精度运算符
    Hello World!
    【JavaScript】7-13 日K蜡烛图 (15分)
    【JavaScript】7-12 两个数的简单计算器 (10分)
    【JavaScript】7-11 分段计算居民水费 (10分)
  • 原文地址:https://www.cnblogs.com/lifehappiness/p/12822974.html
Copyright © 2011-2022 走看看