AT_abc357_d [ABC357D] 88888888
由于忘记等比数列求和公式痛失 D 题。
我们先按题意进行模拟。
记 \(k=\log_{10}n\),可得最后的 \(ans=(n\times k+n)\times k+n...\)。
我们可以把 \(\times k+n\) 认为把当前数字向左移动 \(k\) 位并放置一个 \(n\),当然,最后一次放置不需要再向左移动。
将上式展开可得 \(ans=\sum \limits _{i=0}^{n-1} n\times k^i=n\times \sum \limits _{i=0}^{n-1} k^i\)。
\(\sum \limits _{i=0}^{n-1} k^i\) 显然是等比数列,可以用 \(S=\frac{k^n-1}{k-1}\) 来 \(O(1)\) 求出。(这个柿子是经过 \(\frac{a_nq-a_1}{q-1}\) 简化而来,更详细的等差数列推导可看百度百科)
本题有模数 \(998244353\),用逆元处理乘法即可。不推荐使用 c++ 自带的 log10 函数。
code:
#include<iostream>
#include<algorithm>
#define mod 998244353
#define int __int128
//#include<bits/stdc++.h>
//using namespace std;
long long n;
inline int read(){
int s=0;
int w=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())
if(ch=='-')
w=-1;
for(;ch>='0' and ch<='9';ch=getchar())
s=s*10+ch-'0';
return s*w;
}
void write(int x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
return;
}//快读快写
int logd(int x){
int cnt=0;
while(x){
x/=10;
cnt++;
}
return cnt;
}//代替log10函数
int qpow(int b,int p){
int ans=1;
int tmp=b;
while(p){
if(p&1)
ans=ans*tmp%mod;
tmp=tmp*tmp%mod;
p>>=1;
}
return ans%mod;
}//快速幂
signed main(){
n=read();
int k=qpow(10,logd(n));
write(n*(qpow(k,n)-1)%mod*(qpow(k-1,mod-2))%mod);//费马小定理求逆元
return 0;//撒花!
}