1007: Pass!
1 0
0 1
10 2
90 3
910 4
9090 5
90910 6
909090 7
9090910
90909090
909090910
\(f_i = f_{i-1} * 9 + f_{i-2} * 10\)
\(f_i + f_{i-1} = 10^x\)
\(if(奇) f_i = (f_{i-1} - 1) * 10\)
\(else f_i = (f_{i-1} + 1) * 10\)
1、假设x是偶数项 \(-> x + (x - 1) * 10 = 10^m\)\((m & 1 == 0)\)
2、假设x是奇数项 \(-> x + (x + 1) * 10 = 10^m\)\((m & 1 == 1)\)
通用即将10改为(n - 1)
TLE:
优化
1、偶数项优化:即 \(x\) + \((x - 1)\) * 10 = \(100^m\) -> \(ans = 2 * m\)
2、奇数项优化:变为 \(x\) * \(inv(n - 1) + 1 + x\) = \(100^m\) -> \(ans = 2 * m + 1\)
还是不行
优化:将两项放在一起 -> 显然两项都是\(100^m\),一起求
还是不行
优化:将\(map\) -> \(unordered_map\)
ok!
BGSG:
const int mod = 998244353;
inline int ksm(int a, int b) {
int res = 1;
while(b) {
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
inline int inv(int x) {
return ksm(x, mod - 2);
}
int log(int a, int b, int ans1, int ans2) {
int m = sqrt(mod + 0.5), v = inv(ksm(a, m));
unordered_map<int, int> mp; mp[1] = 0;
for(int i = 0, e = 1; i < m; ++ i, e = e * a % mod) {
if(e == ans1) return i * 2;
if(e == ans2) return i * 2 + 1;
if(!mp.count(e)) mp[e] = i;
}
for(int i = 0, mul = 1; i < m; ++ i, mul = mul * v % mod) {
if(mp.count(ans1 * mul % mod)) return (i * m + mp[ans1 * mul % mod]) * 2;
if(mp.count(ans2 * mul % mod)) return (i * m + mp[ans2 * mul % mod]) * 2 + 1;
}
return -1;
}
void run() {
//printf("%lld\n", ksm(10, 196003445));
int n = rd(), x = rd(), pre = 1;
/*for(int i = 1; i <= 10; ++ i) {
if(i & 1) printf("%lld\n", pre = (pre - 1) * (n - 1));
else printf("%lld\n", pre = (pre + 1) * (n - 1));
}*/
if(x == 1) {
puts("0");
return ;
}
if(x == 0) {
puts("1");
return ;
}
int y = (x - 1) * (n - 1) % mod;
int ans1 = (x + y) % mod;
//x = (x + 1) * (n - 1) % mod;
//(prex - 1) * (n - 1) = x
//prex = x / (n - 1) + 1
y = (x * ksm(n - 1, mod - 2) + 1) % mod;
int ans2 = (x + y) % mod;
int res = log((n - 1) * (n - 1) % mod, (x + y) % mod, ans1, ans2);//偶数项
printf("%lld\n", res % mod);
/*x = (x + 1) * (n - 1) % mod;
y = (x - 1) * (n - 1) % mod;
res = log((n - 1) * (n - 1) % mod, (x + y) % mod);//奇数项
if(res != -1) printf("%lld\n", (res * 2 % mod - 1 + mod) % mod);
else puts("-1");*/
return ;
}
signed main() {
int t = rd();
while(t--) run();
return 0;
}
1010: zoto
\(x\)轴莫队,对\(y\)轴维护一个分块
这样修改的复杂度是\(O(1 * \sqrt n)\)的,查询的复杂度是$O(\sqrt n) $的
三维偏序 CDQ咋做呀
const int maxn = 1e5 + 10;
int n, m, sz, bnum;
int a[maxn], ans[maxn], pos[maxn];
struct query{
int l, r, y1, y2, id;
bool operator < (const query & a) const {
return (pos[l] ^ pos[a.l]) ? pos[l] < pos[a.l] : ((pos[l] & 1) ? r < a.r : r > a.r);
}
}q[maxn];
int num[maxn], sum[maxn];
inline void add(int x) {
(!num[x]++)&&(++sum[x / sz]);
}
inline void del(int x) {
(!--num[x])&&(--sum[x / sz]);
}
int calc(int x) {
int res = 0;
for(int i = 0; i < x / sz; ++ i) res += sum[i];
for(int i = x / sz * sz; i <= x; ++ i) res += num[i] ? 1 : 0;
return res;
}
void run() {
n = rd(), m = rd();
memset(num, 0, sizeof num);
memset(sum, 0, sizeof sum);
sz = sqrt(n), bnum = ceil(1.0 * n / sz);
for(int i = 1; i <= bnum; ++ i) for(int j = (i - 1) * sz + 1; j <= i * sz; ++ j) pos[j] = i;
for(int i = 1; i <= n; ++ i) a[i] = rd();
for(int i = 1; i <= m; ++ i)
q[i].l = rd(), q[i].y1 = rd(), q[i].r = rd(), q[i].y2 = rd(), q[i].id = i;
sort(q + 1, q + 1 + m); int l = 1, r = 0;
for(int i = 1; i <= m; ++ i) {
while(l < q[i].l) del(a[l++]);
while(l > q[i].l) add(a[--l]);
while(r < q[i].r) add(a[++r]);
while(r > q[i].r) del(a[r--]);
ans[q[i].id] = calc(q[i].y2) - calc(q[i].y1 - 1);
}
for(int i = 1; i <= m; ++ i) printf("%lld\n", ans[i]);
}