AtCoder Beginner Contest 357 D(数学)
前言
本来想 vp D~G的,结果赛时 D 还没调出来。一看题解恍然大悟,感觉智商被按在地上摩擦。
My Solution
假设 \(n\) 有 \(k\) 位,最后结果一定是 \(n((10^k)^0+(10^k)^1+...+(10^k)^{n-1})\)。那么问题就变为了解决:快速求 \(((10^k)^0+(10^k)^1+...+(10^k)^{n-1})\)
考虑倍增。预处理 \(f_i\) 表示 \(((10^k)^0+(10^k)^1+...+(10^k)^{2^i-1})\),\(n\) 拆解为二进制数累计贡献即可。
注意要用欧拉定理(本题其实就是费马小定理)对指数取模。(\(x^y \equiv x^{y \% \phi(mod)} ( \% mod)\),因为 \(mod=998244353\) 是质数,所以 \(\phi(mod)=mod-1\))
My Code
PS:自己造的样例是错的,在那里调了半天。
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
return x * f;
}
const int mod = 998244353;
int f[64];
int Pow(int x,int y) {
int res = 1, base = x;
while(y) {
if(y&1) res = res*base%mod;
base = base*base%mod;
y >>= 1;
}
return res;
}
signed main()
{
string s;
cin >> s;
int k = s.length();
int n = stoll(s);
f[0] = 1;
for(int i=1;i<64;++i) {
f[i] = f[i-1]*((1+Pow(10, ((1ll<<(i-1))%(mod-1))*k%(mod-1)))%mod) % mod;
}
int cnt = 0;
for(int j=63;j>=0;--j) {
if(!((n>>j)&1ll)) continue;
cnt = cnt*Pow(10, (((1ll<<(j))%(mod-1))*k)%(mod-1)) % mod;
cnt = (cnt + f[j]) % mod;
}
int ans = (n%mod)*cnt % mod;
printf("%lld\n",ans);
return 0;
}
Std Solution
令 \(x = 10^k\) ,原式 \(=n(1+x^1+...+x^{n-1})=n\frac{1-x^n}{1-x} (\% mod)\),注意 \(\frac{1}{1-x} = (1-x)^{mod-2}(\% mod)\)(费马小定理)。
Code
注意 \(n \le 10^18\),最后算的时候 \(n\) 要先取模再乘,不然会直接爆 long long
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
return x * f;
}
const int mod = 998244353;
int Pow(int x,int y) {
int res = 1, base = x;
while(y) {
if(y&1) res = res*base%mod;
base = base*base%mod;
y >>= 1;
}
return res;
}
int Inv(int x) {
return Pow(x, mod-2);
}
signed main()
{
string s;
cin >> s;
int k = s.length();
int n = stoll(s);
int x = Pow(10, k);
int ans = (n%mod)*(Pow(x, n)-1)%mod*Inv((x-1+mod)%mod)%mod;
ans = (ans%mod + mod) % mod;
printf("%lld",ans);
return 0;
}