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;
}
posted @ 2024-06-28 13:42  基地AI  阅读(10)  评论(0编辑  收藏  举报