A、牛牛和牛可乐的赌约

正面不容易直接得到答案,那就 1 - 反面的答案。如果我们求得不是他输的概率而是赢的概率的话,那就十分好求答案就是,我们直接拿1减掉,再通过费马小定理,逆元运算求得MOD下的值即可。

#pragma GCC target("avx,sse2,sse3,sse4,popcnt")
#pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math")
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)    putchar(op); return; }    char F[40]; ll tmp = x > 0 ? x : -x;    if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]);    if (op)    putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
inline int lowbit(int x) { return x & (-x); }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;

const int N = 1e5 + 7;
int main() {
    int T = read();
    while (T--) {
        ll a = read(), b = read();
        ll ans = (qpow(a, b, MOD) - 1) * qpow(qpow(a, b, MOD), MOD - 2, MOD) % MOD;
        print(ans);
    }
    return 0;
}

B、牛牛和牛可乐的赌约2

规律打表题,贴出我的Excel表格图就可以发现规律,当下标(i - j) % 3 = 0时先手就是输的。
图片说明

#pragma GCC target("avx,sse2,sse3,sse4,popcnt")
#pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math")
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)    putchar(op); return; }    char F[40]; ll tmp = x > 0 ? x : -x;    if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]);    if (op)    putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
inline int lowbit(int x) { return x & (-x); }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;

const int N = 1e5 + 7;

int main() {
    int T = read();
    while (T--) {
        ll n = read(), m = read();
        if (abs(n - m) % 3)
            puts("yyds");
        else
            puts("awsl");
    }
    return 0;
}

C、单词记忆方法

括号递归处理,使用全局下标进行字符串遍历,依次对括号进行递归计算,再统计即可,注意开启long long。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e5 + 7;
char s[N];
int i;

ll solve() {
    ll ans = 0, tmp = 0;
    for (; s[i]; ++i) {
        int num = 0;
        while (s[i] and isdigit(s[i])) {
            num = num * 10 + s[i] - '0';
            ++i;
        }
        ans += tmp * (num ? num : 1);

        tmp = 0;
        if (isalpha(s[i]))
            tmp = s[i] - 'A' + 1;
        else if (s[i] == '(')
            ++i, tmp = solve();
        else
            break;
    }
    return ans + tmp;
}

int main() {
    scanf("%s", s);
    printf("%lld\n", solve());
    return 0;
}

D、位运算之谜

图片说明

#pragma GCC target("avx,sse2,sse3,sse4,popcnt")
#pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math")
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)    putchar(op); return; }    char F[40]; ll tmp = x > 0 ? x : -x;    if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]);    if (op)    putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
inline int lowbit(int x) { return x & (-x); }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;

const int N = 1e5 + 7;
//  a = 9
//  b = 1
//  10,1
//  a = 1001
//  b = 0001

// 11
// 01
// 01
// 11
// 111
// 001
int main() {
    int T = read();
    while (T--) {
        ll n = read(), m = read();
        n -= m * 2;
        if (n < 0 or (n & m)) {
            print(-1);
            continue;
        }
        print(n);
    }
    return 0;
}

G、牛牛和字符串的日常

std中string的用法以及二分。
对于每次输入的字符串,通过二分去查找前缀是否存在,累加计数即可。

#include <bits/stdc++.h>
using namespace std;

int main () {
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    string a,b;
    cin >> a;
    int T;
    cin >> T;
    int ans = 0;
    while(T--){
        cin >> b;
        int l=1,r=b.size(),tmp=0;
        while(l<=r){
            int mid=l+r>>1;
            if(b.find(a.substr(0,mid))!=b.npos)
                tmp = mid, l = mid + 1;
            else
                r=mid-1;
        }
        ans += tmp;
    }
    cout<<ans<<'\n';
    return 0;
}

H、上学要迟到了

建图思维+dijkstra最短路算法
最短路不难,这题主要思考如何建图出来,因为车子只会在起点开始,终点结束,说明每辆车都最多只有2个站台,但是人却可以往前往后走路前进,这时候我们把地图中的全部站台相邻两个之间通过无向图建立联系,时间花费就是走路的花费。并且记录当前下标处来的车是什么,如果这是第二次出现,说明到了终点站了,建立起点到终点之间的一条有向路。到此建图完毕,跑一边最短路算法即可得到最终答案。

#include <bits/stdc++.h>
using namespace std;
#define pai pair<int,int>
const int N = 2e5 + 7;
struct Node {
    int v, w;
    int next;
}edge[N << 1];

bool vis[N];
int head[N], dis[N], tot;

void add(int u, int v, int w) {
    ++tot;
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot;
}

void dijkstra(int s, int t) {
    memset(vis, 0, sizeof vis);
    memset(dis, 0x3f, sizeof dis);
    priority_queue<pai, vector<pai>, greater<pai>> pq;
    pq.push({ 0,s });
    dis[s] = 0;
    while (pq.size()) {
        pai now = pq.top();    pq.pop();
        int u = now.second;
        if (vis[u])    continue;
        vis[u] = 1;
        for (int i = head[u]; i; i = edge[i].next) {
            int v = edge[i].v, w = edge[i].w;
            if (vis[v])    continue;
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                pq.push({ dis[v],v });
            }
        }
    }
}

unordered_map<int, int> pre;
int a[N];

int main() {
    int n, m, s, t, T;
    scanf("%d %d %d %d %d", &n, &m, &s, &t, &T);
    for (int i = 1; i <= m; ++i)
        scanf("%d", a + i);
    int x;
    scanf("%d", &x);
    pre[x] = 1;
    for (int i = 2; i <= n; ++i) {
        add(i - 1, i, T);
        add(i, i - 1, T);
        scanf("%d", &x);
        if (pre[x])    add(pre[x], i, a[x]);
        pre[x] = i;
    }
    dijkstra(s, t);
    printf("%d\n", dis[t]);
    return 0;
}

I、迷宫

首先观察数据范围,
先试试,1e8的bool数组下随便测一下会不会MLE,发现不会!那就要把思维从BFS转变为递推了。
我们开启一个 dp[n][m][MOD]的三维数组,如果dp[i][j][c] = 1,说明在i,j处花费为c的情况可以被走到。
这样的话就变成一个动态规划问题,枚举各个点,再枚举一下c的取值,如果他上面某个点加上当前枚举的点花费刚好等于枚举的c,而且上方的点取值已经没确定是1的情况下,当前点的c值也赋值成1。

#pragma GCC target("avx,sse2,sse3,sse4,popcnt")
#pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math")
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)    putchar(op); return; }    char F[40]; ll tmp = x > 0 ? x : -x;    if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]);    if (op)    putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
inline int lowbit(int x) { return x & (-x); }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e4 + 7;
const int INF = 0x3f3f3f3f;

const int N = 100 + 7;
bool dp[N][N][MOD];
int a[N][N];

int main() {
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            a[i][j] = read();
    dp[1][1][a[1][1] % MOD] = 1;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) {
            if (i == 1 and j == 1)    continue;
            for (int k = 0; k < MOD; ++k) {
                int c = ((k - a[i][j]) % MOD + MOD) % MOD;
                if (dp[i - 1][j][c] or dp[i][j - 1][c])
                    dp[i][j][k] = 1;
            }
        }
    int cnt = 0;
    for (int i = 0; i < MOD; ++i)
        cnt += dp[n][m][i];
    print(cnt);
    return 0;
}

J、树上行走

并查集,连通块维护。
维护一下每个连通块的大小,再合并的时候观察是不是同一个颜色的,还有最后注意大小等于最大的连通块全部都要输出。

#pragma GCC target("avx,sse2,sse3,sse4,popcnt")
#pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math")
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)    putchar(op); return; }    char F[40]; ll tmp = x > 0 ? x : -x;    if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]);    if (op)    putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
inline int lowbit(int x) { return x & (-x); }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;

const int N = 2e5 + 7; //节点数
const int M = 2e5 + 7; //路径数
int head[N], tot = 0;//前向星变量
struct Node {
    int u; //起点
    //int w; //权值
    int v;
}edge[N];

int ans = 1;
int a[N];

int fa[N], sz[N];
int find(int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

void merge(int u, int v) {
    int fu = find(u), fv = find(v);
    fa[fv] = fu;
    sz[fu] += sz[fv];
    if (ans < sz[fu])
        ans = sz[fu];
}

int main() {
    int n = read();
    for (int i = 1; i <= n; ++i) {
        fa[i] = i, sz[i] = 1;
        a[i] = read();
    }
    for (int i = 1; i < n; ++i) {
        edge[i].u = read(), edge[i].v = read();
        if (a[edge[i].u] != a[edge[i].v])
            continue;
        merge(edge[i].u, edge[i].v);
    }
    vector<int> res;
    for (int i = 1; i <= n; ++i) {
        if (sz[find(i)] == ans)
            res.push_back(i);
    }
    print(res.size());
    for (auto it : res)
        print(it, 32);
    return 0;
}