https://ac.nowcoder.com/acm/contest/8051

C - 有用的 LCM

 

题意:定义前缀 lcm 为 Ln=lcm(1,2,3,...,n)L_n= lcm(1,2,3,...,n) ,且一个数 x 对其前缀 lcm 有贡献当且仅当 Lx1LxL_{x-1}\not= L_x 。特别的, 1 不视为对其前缀 lcm 有贡献。现在你需要求出 1~ n 内所有对其前缀 lcm 有贡献的数的个数。

min25筛

显然答案是 p 的幂次的个数。

只有小于等于 n\sqrt{n} 的质数有大于 1 的幂次,对于这些质数欧拉筛出来,同时统计幂次的个数。

还需要得到小于等于 nn 的质数的个数,min25筛模板题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <bits/stdc++.h>
#define debug(x) cout << #x << ":\t" << (x) << endl;
using namespace std;
#define ll long long
const int N = 2e6 + 10;
const int INF = 0x3f3f3f3f;
const ll inf = 0x3f3f3f3f3f3f3f3f;
ll n, ans;
int vis[N], prime[N], cnt, sqr;
ll sieve(int m) {
ll res = 0;
for (int i = 2; i <= m; i++) {
if (!vis[i]) {
prime[++cnt] = i;
ll x = n;
while (x >= i) {
x /= i;
res++;
}
res--;
}
ll d;
for (int j = 1; j <= cnt && (d = 1ll*i * prime[j]) <= m; j++) {
vis[d] = 1;
if (i%prime[j] == 0)break;
}
}
return res;
}
ll w[N]; int m;
ll g[N];
int id[2][N];
int main() {
scanf("%lld", &n);
sqr = (int)sqrt(n);
ans = sieve(sqr);
for (ll i = 1, j; i <= n; i = j + 1) {
j = n / (n / i);
w[++m] = n / i;
if (w[m] <= sqr)id[0][w[m]] = m;
else id[1][n / w[m]] = m;
g[m] = w[m] - 1;
}
for (int j = 1; j <= cnt; j++) {
for (int i = 1; i <= m && w[i] >= 1ll*prime[j] * prime[j]; i++) {
int k = (w[i] / prime[j] <= sqr ? id[0][w[i] / prime[j]] : id[1][n / (w[i] / prime[j])]);
ll tmp = g[k] - j + 1;
g[i] -= tmp;
}
}
printf("%lld\n", g[1] + ans);
return 0;
}

 

斐波那契?数列!

 

题意:题目分为两小部分。 第一个部分中你需要求出:对于递推数列 ai=xai1+yai2+zai3a_i=x·a_{i-1}+y·a_{i-2}+z·a_{i-3} 的前缀平方和 i=1nai2\sum_{i=1}^{n} a_i^2 ;第二个部分你需要回答 q 个询问:对于每个询问值 x 你需要回答:斐波那契数列 fif_i 的前缀平方和 FxF_x 的值。

第一部分,矩阵快速幂直接求即可。

第二部分,有结论 i=1nfi2=fifi+1\sum_{i=1}^nf_i^2=f_i\cdot f_{i+1}

需要快速求出 fif_i,但是由于 55 在模 998244353 下没有二次剩余,所有不能套公式。

但是又有结论

(fn+1fnfnfn1)=(1110)n(f2n+1f2nf2nf2n1)=(1110)2n(f2n+1f2nf2nf2n1)=(fn+1fnfnfn1)2\begin{pmatrix} f_{n+1} & f_{n} \\ f_{n} & f_{n-1} \\ \end{pmatrix}= \begin{pmatrix} 1 & 1 \\ 1 & 0 \\ \end{pmatrix}^{n}\\ \begin{pmatrix} f_{2n+1} & f_{2n} \\ f_{2n} & f_{2n-1} \\ \end{pmatrix}= \begin{pmatrix} 1 & 1 \\ 1 & 0 \\ \end{pmatrix}^{2n}\\ \Downarrow\\ \begin{pmatrix} f_{2n+1} & f_{2n} \\ f_{2n} & f_{2n-1} \\ \end{pmatrix}= \begin{pmatrix} f_{n+1} & f_{n} \\ f_{n} & f_{n-1} \\ \end{pmatrix}^2

所以可以 O(logx)O(\log x) 求出 fx,fx+1f_x,f_{x+1}

注意 nn 要用 __int128.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <bits/stdc++.h>
#define debug(x) cout << #x << ":\t" << (x) << endl;
using namespace std;
#define ll long long
const int N = 2e6 + 10;
const int INF = 0x3f3f3f3f;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
inline __int128 read()
{
__int128 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 * 10 + ch - '0';
ch = getchar();
}
return x * f;
}

inline void write(__int128 x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}

__int128 n;
ll a1, a2, a3, x, y, z;
int q;
struct Mat
{
ll a[10][10];
int r, c;
Mat(int _r, int _c) { r = _r, c = _c, memset(a, 0, sizeof(a)); }
};
Mat operator*(Mat X, Mat Y) {
Mat Z(X.r, Y.c);
for (int i = 0; i < X.r; i++) {
for (int j = 0; j < Y.c; j++) {
for (int k = 0; k < X.c; k++) {
Z.a[i][j] = (Z.a[i][j] + 1ll * X.a[i][k] * Y.a[k][j] % mod) % mod;
}
}
}
return Z;
}
Mat pow(Mat a, __int128 n) {
Mat res(a.r, a.c);
for (int i = 0; i < a.r; i++)
res.a[i][i] = 1;
while (n > 0) {
if (n % 2 != 0)res = res * a;
a = a * a;
n /= 2;
}
return res;
}
Mat A(7, 1), B(7, 7);
typedef pair<int, int>pii;
pii fib(int n) {
if (n == 0) return { 0, 1 };
pii p = fib(n >> 1);
if (n & 1) {
int a = (1ll * p.first*p.first%mod + 1ll * p.second*p.second%mod) % mod;
int b = 1ll * p.second*(2ll * p.first%mod + p.second) % mod;
return { a,b };
}
else {
int a = 1ll * p.first*(2ll * p.second%mod - p.first + mod) % mod;
int b = (1ll * p.first*p.first%mod + 1ll * p.second*p.second%mod) % mod;
return { a,b };
}
}
int main() {
n = read();
scanf("%lld%lld%lld%lld%lld%lld", &a1, &a2, &a3, &x, &y, &z);
A.a[0][0] = (a1 * a1 + a2 * a2 + a3 * a3) % mod;
A.a[1][0] = a3 * a3%mod; A.a[2][0] = a2 * a2%mod; A.a[3][0] = a1 * a1%mod;
A.a[4][0] = a3 * a2%mod; A.a[5][0] = a3 * a1%mod; A.a[6][0] = a2 * a1%mod;
for (int i = 0; i < 2; i++) {
B.a[i][1] = x * x%mod; B.a[i][2] = y * y%mod; B.a[i][3] = z * z%mod;
B.a[i][4] = 2 * x*y%mod; B.a[i][5] = 2 * x*z%mod; B.a[i][6] = 2 * y*z%mod;
}
B.a[0][0] = 1; B.a[1][0] = 0;
B.a[2][1] = B.a[3][2] = B.a[6][4] = 1;
B.a[4][1] = x; B.a[4][4] = y; B.a[4][5] = z;
B.a[5][2] = y; B.a[5][4] = x; B.a[5][6] = z;
if (n == 1)printf("%lld\n", a1*a1%mod);
else if (n == 2)printf("%lld\n", (a1*a1 + a2 * a2) % mod);
else {
A = pow(B, n - 3)*A;
printf("%lld\n", A.a[0][0]);
}
scanf("%d", &q);
while (q--) {
int i;
scanf("%d", &i);
auto p = fib(i);
int ans = 1ll * p.first * p.second % mod;
printf("%d\n", ans);
}
return 0;
}