Maybe something will|

Semorius

园龄:1年9个月粉丝:4关注:10

2023-10-06 19:14阅读: 45评论: 0推荐: 0

[ABC322G] Two Kinds of Base

第一次赛后马上AK ABC,好激动,感觉是这场太水了,一看评分,G有2800?!

感觉这个 Trick 挺有用的:某些变量真正能取到的值其实远远没有给的范围那么大,除了某些特殊情况,而这些特殊情况可以用特殊的方式统计答案。

题意

对于一个非负整数序列 S=(S1,S2,,Sk) 和一个整数 a,定义函数 f(S,a) 如下:

f(S,a)=i=1kSi×aki

给定正整数 NX。求满足以下所有条件的非负整数序列 S=(S1,S2,,Sk) 和正整数 ab 的三元组 (S,a,b) 的数量模 998244353

  • k1
  • a,bN
  • S10
  • Si<min(10,a,b)(1ik)
  • f(S,a)f(S,b)=X

思路

首先,可以把数列 S 分别看做是 ka 进制数和 kb 进制数每一位上的值,记这两个数分别记作 AB。题目中的最后一个限制就等价于 AB=X,其中 X 是十进制意义下的。

显然 f(S,a)f(S,b)=i=1kSi×(akibki),由于 X 为正整数,故 a>b

所以上式的这一部分 akibkii 增大单调递减,当 i=k 时,a0b0=0,即 Sk 的取值不会对 AB 的值产生影响。

考虑最朴素的做法,枚举 k,a,b,并构造一种合理的 S 使得满足上述限制。可以证明,如果存在这样的一个 S,那么 (S1,S2,,Sk1) 是唯一的。

证明:假设从 i=1 开始依次填 Si,设 X 表示 X 减去 S1Si1 的总贡献后的值, Si+1Sk 能产生的最大贡献为 CSi=1 时仅 Si 产生的贡献为 D。能得到:D=akibki=(a1)×j=i+1kakj(b1)×j=i+1kbkj>(b1)×(j=i+1kakj×j=i+1kbkj)。所以,当 X>C 时,只有 Si=Xakibki 时才有可能满足条件。而当 XC 时,Si 只能等于 0。如此贪心地往下填 S 的每一位,一直到 Sk1,能确定一组唯一的 (S1,S2,,Sk1)

这样在固定 k,a,b 的情况下可以 O(k) 地统计答案,k 的范围是 O(logX) 级别,但 a,b 的范围却是与 n 同阶的。

其实有效的 a,b 远没有这么多。

由于 S10,这等价于 ak1bk1X,可以发现,当 k3 时,满足这个条件的二元组 (a,b) 是很少的(当 N=109,X=2×105 时,只有 620787 组),每一次可以用 O(logX) 的时间统计答案。

而当 k=2 时,X=(ab)×S1,用 O(x) 的时间统计答案即可。

Code

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define l(x) x<<1
#define r(x) x<<1|1
#define mpr make_pair
//mt19937_64 ra(time(0) ^ (*new char));
const ll SIZE = 200005;
const ll mod = 998244353;
ll n, X, ans;
inline ll rd(){
ll f = 1, x = 0;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return f*x;
}
ll power(ll x, ll y){
ll jl = 1;
while(y){
if(y & 1) jl = (jl * x);
x = (x * x);
y >>= 1;
}
return jl;
}
int main(){
n = rd(), X = rd(); ll cnt = 0;
for(ll i = 1; i*i <= X; i++){
if(X%i == 0){
if(i < 10){
for(ll a = i+1+(X/i); a <= n; a++){
ll b = a-(X/i);
if(b >= 10) break;
ans = (ans + min(10ll, b)) % mod;
}
if(n-(X/i) >= 10){
ans = (ans + (10 * (n-(X/i)-10+1)) % mod) % mod;
}
}
if(i != (X/i) && (X/i) < 10){
for(ll a = (X/i)+1+i; a <= n; a++){
ll b = a-i;
if(b >= 10) break;
ans = (ans + min(10ll, b)) % mod;
}
if(n-i >= 10){
ans = (ans + (10 * (n-i-10+1)) % mod) % mod;
}
}
}
}
for(ll k = 3; k <= 20; k++){
for(ll a = 1; a <= n; a++){
if(power(a, k-1)-power(a-1, k-1) > X) break;
for(ll b = a-1; b >= 1; b--){
if(power(a, k-1)-power(b, k-1) > X) break;
ll jl = X; bool flag = 1;
for(ll i = 1; i < k; i++){
if(jl / (power(a, k-i)-power(b, k-i)) >= min(10ll, min(a, b))) flag = 0;
jl = (jl % (power(a, k-i)-power(b, k-i)));
}
if(jl == 0 && flag){
ans = (ans + min(10ll, min(a, b))) % mod;
}
}
}
}
printf("%lld", ans);
return 0;
}

本文作者:Semorius

本文链接:https://www.cnblogs.com/Semorius/p/17744863.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Semorius  阅读(45)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起