校赛部分题解
校赛部分题解
ps: 某毒瘤出题人的题解
A,第一集,这是怎么肥死嘛
统计字母签到题
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
int t, n;
char str[MAXN];
int cnt[10];
int main()
{
map<char, int>mp;
//hello world
mp['h'] = 1; // 1
mp['e'] = 2; // 1
mp['l'] = 3; // 3
mp['o'] = 4; // 2
mp['w'] = 5; // 1
mp['r'] = 6; // 1
mp['d'] = 7; // 1
scanf("%d", &t);
while(t--) {
scanf("%s", str);
n = strlen(str);
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < n; i++ ) {
if(mp.count(str[i])) {
cnt[ mp[str[i]] ]++;
}
}
cnt[ mp['l'] ] /= 3;
cnt[ mp['o'] ] /= 2;
int ans = 0x3f3f3f3f;
for(int i = 1; i <= 7; i++ ) {
ans = min(ans, cnt[i]);
}
printf("%d\n", ans);
}
return 0;
}
/**
3
helloworld
helloworldooooooooooo
helloworldhelloworldasjdkl
*/
I, 第五集,不要007,要睡觉
类似题: HDU 5950,我随手改了递推式
这么裸的矩阵快速幂 F[n] = 2 * f[n - 1] + 3 * f[n - 2] + 3 * n^5
, 除了那个n^5。
第一项,第二项直接输出答案
当 n >= 3 时, 我们假设
\[A_n=\left[
\begin{matrix}
F[n] & F[n-1] & n^5 & n^4 & n^3 & n^2 & n^1 & n^0\\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
\end{matrix}
\right]
\]
\[A_{n+1}=\left[
\begin{matrix}
F[n+1] & F[n] & (n+1)^5 & (n+1)^4 & (n+1)^3 & (n+1)^2 & n+1 & 1\\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
\end{matrix}
\right]
\]
假设一个矩阵B, 我们需要算一个B使得
\[A_{n+1} = A_n * B
\]
按照矩阵乘法规则易得
\[B=\left[
\begin{matrix}
2 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\
3 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
3 & 0 & 1 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 5 & 1 & 0 & 0 &0 &0 \\
0 & 0 & 10 & 4 & 1 & 0 &0 &0 \\
0 & 0 & 10 & 6 & 3 & 1 &0 &0 \\
0 & 0 & 5 & 4 & 3 & 2 &1 &0 \\
0 & 0 & 1 & 1 & 1 & 1 &1 &1 \\
\end{matrix}
\right]
\]
所以我们假设
\[A = \left[
\begin{matrix}
b & a & 3^5 & 3^4 & 3^3 & 3^2 & 3^1 & 3^0\\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
\end{matrix}
\right]
\]
\[B = \left[
\begin{matrix}
2 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\
3 & 0 & 0 & 0 & 0 & 0 &0 &0 \\
3 & 0 & 1 & 0 & 0 & 0 &0 &0 \\
0 & 0 & 5 & 1 & 0 & 0 &0 &0 \\
0 & 0 & 10 & 4 & 1 & 0 &0 &0 \\
0 & 0 & 10 & 6 & 3 & 1 &0 &0 \\
0 & 0 & 5 & 4 & 3 & 2 &1 &0 \\
0 & 0 & 1 & 1 & 1 & 1 &1 &1 \\
\end{matrix}
\right]
\]
令矩阵 C = A * B ^ (n - 2), 答案为C[0][0]
标称
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 110;
typedef long long LL;
const LL MOD = 2147493647;
#define mod(x) ((x)%MOD)
int n = 8;
struct Mat {
LL m[MAXN][MAXN];
void init() {
memset(m, 0, sizeof(m));
}
void set() {
init();
for(int i = 0; i < MAXN; i++ ) {
m[i][i] = 1;
}
}
void disp() {
for(int i = 0; i < n; i++ ) {
for(int j = 0; j < n; j++ ) {
printf("%-10d", m[i][j]);
}
puts("");
}
}
} unit;
Mat operator * (const Mat &a, const Mat &b) {
Mat ret;
ret.init();
LL x = 0;
for(int i = 0; i < n; i++ ) {
for(int j = 0; j < n; j++ ) {
x = 0;
for(int k = 0; k < n; k++ ) {
x += mod((a.m[i][k] % MOD) * (b.m[k][j] % MOD));
x = mod(x);
}
ret.m[i][j] = mod(x);
}
}
return ret;
}
Mat pow_mod(Mat a, LL n) {
Mat ret = unit;
while(n) {
if(n & 1) {
ret = ret * a;
}
a = a * a;
n >>= 1;
}
return ret;
}
LL pow_mod(LL a, LL b) {
LL res = 1;
while(b) {
if(b & 1) {
res = (res * a) % MOD;
}
b >>= 1;
a = (a * a) % MOD;
}
return res;
}
int T;
LL N, a, b;
int map_b[8][8] =
{
2, 1, 0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 0, 0, 0,
3, 0, 1, 0, 0, 0, 0, 0,
0, 0, 5, 1, 0, 0, 0, 0,
0, 0,10, 4, 1, 0, 0, 0,
0, 0,10, 6, 3, 1, 0, 0,
0, 0, 5, 4, 3, 2, 1, 0,
0, 0, 1, 1, 1, 1, 1, 1
};
LL solve_check()
{
if(N == 1) {
//printf("%lld\n", a);
return a;
}
if(N == 2) {
//printf("%lld\n", b);
return b;
}
LL c = 0;
vector<LL>v;
v.push_back(0);
v.push_back(a);
v.push_back(b);
for(int i = 3; i <= N; i++ ) {
LL va = v[i - 1] * 2;
va %= MOD;
va += v[i - 2] * 3;
va %= MOD;
va += 3 * pow_mod(i, 5);
va %= MOD;
v.push_back(va);
}
return v[N];
}
LL solve_std()
{
if(N == 1) {
//printf("%lld\n", a);
return a;
}
if(N == 2) {
//printf("%lld\n", b);
return b;
}
Mat A, B;
A.init();
B.init();
A.m[0][0] = b;
A.m[0][1] = a;
A.m[0][2] = 3 * 3 * 3 * 3 * 3;
A.m[0][3] = 3 * 3 * 3 * 3;
A.m[0][4] = 3 * 3 * 3;
A.m[0][5] = 3 * 3;
A.m[0][6] = 3;
A.m[0][7] = 1;
for(int i = 0; i < 8; i++ ) {
for(int j = 0; j < 8; j++ ) {
B.m[i][j] = map_b[i][j];
}
}
Mat res = A * pow_mod(B, N - 2);
return res.m[0][0] % MOD;
}
void judge_std()
{
freopen("data.in", "w", stdout);
srand(static_cast<unsigned int>(time(0)));
LL MAX = (1LL << 31);
int cas = 1000;
printf("%d\n", cas);
for(int i = 1; i <= cas; i++ ) {
N = rand() % MAX + 1;
a = rand() % MAX + 1;
b = rand() % MAX + 1;
printf("%lld %lld %lld\n", N, a, b);
continue;
LL ans1 = solve_std();
LL ans2 = solve_check();
if(ans1 != ans2) {
puts(ans1 == ans2 ? "Yes" : "No");
printf("cas = %d %lld %lld %lld\n", i, N, a, b);
printf("%lld %lld\n", ans1, ans2);
puts("error");
return ;
}
}
//puts("Accept");
}
int main()
{
// freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
unit.set();
//judge_std();
scanf("%d", &T);
while(T--) {
scanf("%lld %lld %lld", &N, &a, &b);
printf("%lld\n", solve_std());
}
return 0;
}
L, 第八集,我要是不呢?
类似题: BZOJ 2400 SPOJ839
前置技能网络流最小割
异或运算中二进制位之间没有影响。我们可以把每一位单独处理。
那么对于某一个二进制位。变成了取0和取1,不同就会对答案有贡献,对于边权的贡献最少?
下面我们只针对二进制某一位。
那么我们可以看成两种决策,一种把点归成0, 另一种归为1,那么点的两种决策就会造成贡献,我们要让它最小。就变成二选一的最小割模型了。
我们对原图的边,建立双向边,权为1。对于某一位已知01的点,分别划分两个集合,一个连源点,一个汇点,权无穷大。那么我们求该图的最小割。就会在割掉某些边,使得点属于某一个集合,0集合或者1集合。我们要的边权最小也符合最小割的定义。最后我们跑最大流即可。然后在吧每一位的答案整合。
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 555;
const int MAX_M = 3050 * 2;
int n, m, k;
struct Edge {
int u, v;
} edge[MAX_M];
int p[MAX_N], v[MAX_N];
int vis[MAX_N];
struct Dinic {
static const int MAXN = 500 + 7;
static const int MAXM = MAXN * MAXN;
static const int INF = 0x3f3f3f3f;
int n, m, s, t;
int first[MAXN], cur[MAXN], dist[MAXN], sign;
struct Node {
int to, flow, next;
} edge[MAXM * 4];
inline void init(int start, int vertex, int ss, int tt) {
n = vertex, s = ss, t = tt;
for(int i = start; i <= n; i++ ) {
first[i] = -1;
}
sign = 0;
}
inline void addEdge(int u, int v, int flow) {
edge[sign].to = v, edge[sign].flow = flow, edge[sign].next = first[u];
first[u] = sign++;
}
inline void add_edge(int u, int v, int flow) {
addEdge(u, v, flow);
addEdge(v, u, 0);
}
inline int dinic() {
int max_flow = 0;
while(bfs(s, t)) {
for(int i = 0; i <= n; i++ ) {
cur[i] = first[i];
}
max_flow += dfs(s, INF);
}
return max_flow;
}
bool bfs(int s, int t) {
memset(dist, -1, sizeof(dist));
queue<int>que;
que.push(s), dist[s] = 0;
while(!que.empty()) {
int now = que.front();
que.pop();
if(now == t) {
return 1;
}
for(int i = first[now]; ~i; i = edge[i].next) {
int to = edge[i].to, flow = edge[i].flow;
if(dist[to] == -1 && flow > 0) {
dist[to] = dist[now] + 1;
que.push(to);
}
}
}
return 0;
}
int dfs(int now, int max_flow) {
if(now == t) {
return max_flow;
}
int ans = 0, next_flow = 0;
for(int &i = cur[now]; ~i; i = edge[i].next) {
int to = edge[i].to, flow = edge[i].flow;
if(dist[to] == dist[now] + 1 && flow > 0) {
next_flow = dfs(to, min(max_flow - ans, flow));
ans += next_flow;
edge[i].flow -= next_flow;
edge[i ^ 1].flow += next_flow;
if(ans == max_flow) {
return max_flow;
}
}
}
if(ans == 0) {
return dist[now] = 0;
}
return ans;
}
void find_set_s(int x) {
vis[x] = 1;
for(int i = first[x]; ~i; i = edge[i].next) {
int to = edge[i].to, flow = edge[i].flow;
if(!vis[to] && flow) {
find_set_s(to);
}
}
}
} cwl;
int ans[MAX_N];
int main() {
int t;
scanf("%d", &t);
while(t--) {
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++ ) {
scanf("%d %d", &edge[i].u, &edge[i].v);
}
scanf("%d", &k);
for(int i = 1; i <= k; i++ ) {
scanf("%d %d", &p[i], &v[i]);
}
memset(ans, 0, sizeof(ans));
for(int bit = 0; bit < 31; bit++ ) {
cwl.init(0, n + 1, 0, n + 1);
for(int i = 1; i <= m; i++ ) {
int u = edge[i].u, v = edge[i].v;
cwl.add_edge(u, v, 1);
cwl.add_edge(v, u, 1);
}
for(int i = 1; i <= k; i++ ) {
if((v[i] >> bit) & 1) {
cwl.add_edge(0, p[i], cwl.INF);
} else {
cwl.add_edge(p[i], n + 1, cwl.INF);
}
}
cwl.dinic();
memset(vis, 0, sizeof(vis));
cwl.find_set_s(0);
for(int i = 1; i <= n; i++ ) {
if(vis[i]) {
ans[i] += (1 << bit);
}
}
}
//for(int i = 1; i <= n; i++ ) {
// printf("data = %d\n", ans[i]);
//}
long long res = 0;
for(int i = 1; i <= m; i++ ) {
res += ans[ edge[i].u ] ^ ans[ edge[i].v ];
}
printf("%lld\n", res);
}
return 0;
}