题目链接
题目大意:给你一个数字(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;
}