20260627 总结
按照过题顺序总结。
再也不写线段树了。
F - 斐波那契数列
tag:小数高精度,快速幂,矩阵。
讲一讲怎么得来的矩阵。
正所谓矩阵乘法是第一个矩阵的行乘第二个矩阵的列,写成柿子就是(方阵的乘法)
\[\sum_{k=1}^{n} C_i,_j = A_i,_k \times B_k,_j
\]
则如果设矩阵为
\[\begin{pmatrix}
f[n] & f[n - 1]
\end{pmatrix}
\]
那么乘以个什么得到
\[\begin{pmatrix}
f[n + 1] \\ f[n]
\end{pmatrix}
\]
想推出 \(f[n]\) 直接让 \(f[n - 1] \times 0\) 就可以了。
想推出 \(f[n + 1]\) 直接让 \(f[n] + f[n - 1]\)。
矩阵也就是
\[\begin{pmatrix}
1 && 1\\
0 && 1
\end{pmatrix}
\]
A - Mocha and Math
tag:位运算,模拟,线段树。
思路:首先,观察可得两数与所得的数一定不大于两数。又因为可以做任意次操作,所以任意两个数都可以做与操作。所以只需要将每两数都进行与操作,让数值尽量小即可。
罚时原因:模拟错了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define all(x) (x).begin(), (x).end()
#define inf (1 << 30)
#define lnf (1LL << 60)
typedef pair<int, int> PII;
constexpr int N = 100 + 7;
constexpr int P = 998244353;
int n;
void solve() {
scanf("%d", &n);
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
int ans = a[1];
for (int i = 2; i <= n; i++) ans &= a[i];
printf("%lld\n", ans);
}
int main() {
int oT_To = 1;
scanf("%d", &oT_To);
while (oT_To--) solve();
return 0;
}
B - 选数
tag:搜索,二进制,筛法
思路:首先先搜索出数字和,然后再判断素数。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define all(x) (x).begin(), (x).end()
#define inf (1 << 30)
#define lnf (1LL << 60)
typedef pair<int, int> PII;
constexpr int N = 20 + 7;
constexpr int P = 998244353;
int n, k, a[N];
bool isprime(int x) {
if (x <= 1) return false;
for (int i = 2; i <= x / i; i++) {
if (x % i == 0) return false;
}
return true;
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
ll ans = 0;
for (int S = 0; S < (1 << n); S++) {
ll res = 0;
for (int i = 1; i <= n; i++) {
if (S & (1 << (i - 1))) {
res += a[i];
}
}
if (__builtin_popcount(S) == k && isprime(res)) ++ans;
}
printf("%lld\n", ans);
return 0;
}

浙公网安备 33010602011771号