图片说明
思路:
很显然答案是(1-1/(n^m))%mod,因为是除法取模所以是(n^m - 1)*inv(n^m)即可。这题卡常,如果快速幂用两次必超时,用一次就可以过。
代码:

#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;

typedef long long ll;
ll mod = 1e9 + 7;
//1 - (1/n)^m
ll ksm(ll a,ll b){
    ll res = 1;
    while(b){
        if(b & 1)res = res * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return res;
}
ll inv(ll x){
    return ksm(x,mod - 2);
}
void solved(){
    ll n,m;scanf("%lld%lld",&n,&m); 
    ll ans = ksm(n,m);
    printf("%lld\n", (ans - 1) * inv(ans) % mod);
}
int main(){
    int t;
    while(scanf("%d",&t) != EOF && t > 0){
        while(t--)
            solved();
    }
    return 0;
}

图片说明
思路:打表找规律
图片说明
可以发现abs(x-y)%3=0必败,其他必胜。
代码:

#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;

typedef long long int ll;
void solved(){
    int x,y;
    scanf("%d%d",&x,&y);
    int s = abs(x - y);
    if(x == 0 && y == 0){
        cout<<"awsl"<<endl;
        return ;
    }
    if(s % 3 == 0){
        cout<<"awsl"<<endl;
    }else{
        cout<<"yyds"<<endl;
    }
}
int main(){
    int t;
    while(scanf("%d",&t) != EOF){
        while(t--){
            solved();
        }
    }
    return 0;
}

图片说明
思路:
a&b=y说明a,b的二进制至少大于等于y,所以a+b=x>=2y才有有结果,否则输出-1,a^b为x-全部二进制位相同的即x-2y,并且(x-2y)&y!=0才行因为当x=3,y=1,这种也是不符合情况的。
代码:

#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;

typedef long long int ll;
void solved(){
    ll x,y;scanf("%lld%lld",&x,&y);
    if(x < 2 * y || ((x - 2 * y) & y) != 0){
        cout<<"-1"<<endl;return ;
    }
    cout<<(x - 2 * y)<<endl;
}
int main(){
    int t;scanf("%d",&t);
    while(t--)
        solved();
}

图片说明
思路:
暴力比较+KMP就行了。
代码:

#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;

typedef long long int ll;
const int maxn = 2e5 + 10;
int next[maxn];

vector<int> getnext(string t){
    vector<int>next(t.size());
    for(int i=1,k=0;i<t.size();i++){
        while(k>0&&t[i]!=t[k]){
            k=next[k-1];
        }
        if(t[i]==t[k]){
            next[i]=++k;
        }else{
            next[i]=k;
        }
    }
    return next;
}
int kmp(string t,string s){
    int res = 0;
    vector<int>next=getnext(t);
    for(int i=0,k=0;i<s.size();i++){
        while(k>0&&s[i]!=t[k]){
            k=next[k-1];
        }
        if(t[k]==s[i]){
            k++;
            res = max(res,k);
        }
        if(k==t.size()){
            return t.size();
        }
    }
    return res;
}
void solved(){
    string t,s;
    cin>>t;
    getnext(t);
    int n;scanf("%d",&n);
    int ans = 0;
    for(int i = 1; i <= n; i++){
        cin>>s;
        ans += kmp(t,s);
    }
    printf("%d\n",ans);
}
int main(){
    solved();
}

图片说明
思路:
点与点之间建立双向边权为走路的时间,然后每个车站可以停的地方建立单向边,从源点s到汇点跑最短路即可。
为什么不能建立单向边呢?
图片说明
随便举个例子就hack了。
代码:

#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;

typedef long long int ll;
const int maxn = 2e5 + 10;
struct edge{
    int v,w,next;
}e[maxn << 2];
int Time[maxn];
vector<int>G[maxn];
int head[maxn],tot;
void add(int u,int v,int w){
    e[++tot].v = v;
    e[tot].w = w;
    e[tot].next = head[u];
    head[u] = tot;
}

ll dis[maxn];
struct node{
    ll id,dis;
    bool operator < (const node &a)const{
        return dis > a.dis;
    }
};
void dij(int s,int t){
    priority_queue<node>st;
    st.push(node{s,0});
    dis[s] = 0;
    while(!st.empty()){
        node cur = st.top();st.pop();
        ll u = cur.id;
        ll di = cur.dis;
        if(cur.dis != dis[cur.id])continue;
        for(int i = head[u]; i; i = e[i].next){
            int v = e[i].v;
            if(dis[v] > dis[u] + e[i].w){
                dis[v] = dis[u] + e[i].w;
                st.push(node{v,dis[v]});
            }
        }
    }
    cout<<dis[t]<<endl;
}
void solved(){
    int n,m,s,t,T;scanf("%d%d%d%d%d",&n,&m,&s,&t,&T);
    for(int i = 1; i <= n; i++)dis[i] = 1e9;
    for(int i = 1; i <= m; i++){
        scanf("%d",&Time[i]);
    }
    for(int i = 1; i <= n; i++){
        if(i < n){
            add(i + 1,i,T);
            add(i,i + 1,T);
        }
        int x;scanf("%d",&x);
        if(G[x].size() >= 1){
            add(G[x].back(),i,Time[x]);
        }
        G[x].push_back(i);
    }
    dij(s,t);
}
int main(){
    solved();
    return 0;
}

图片说明
思路:
很显然找最大连通块就行了,枚举顶点然后dfs跑它的连通块,相等的也记录一下。
时间复杂度O(n + m)。虽然枚举了顶点但是实际上只跑了一遍图。
代码:

#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;

const int maxn = 3e5 + 10;
int a[maxn];
vector<int>G[maxn];
bool vis[maxn];
int cnt;
vector<int>res;
void dfs(int u,int color,int f){
    for(int i = 0; i < G[u].size(); i++){
        int v = G[u][i];
        if(v == f)continue;
        if(!vis[v] && a[v] == color){
            vis[v] = true;
            cnt++;
            res.push_back(v);
            dfs(v,color,u);
        }
    }
}
void solved(){
    int n;scanf("%d",&n);
    for(int i = 1; i <= n; i++)scanf("%d",&a[i]);
    for(int i = 1; i <= n - 1; i ++){
        int u,v;scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    cnt = 1;
    int ans = 0;
    vector<int>SS;
    vector<int>add;
    for(int i = 1; i <= n; i++){
        if(!vis[i]){
            res.push_back(i);
            dfs(i,a[i],-1);
            if(cnt == ans){
                for(int k = 0; k < res.size(); k++){
                    add.push_back(res[k]);
                }
            }
            if(cnt > ans){
                ans = max(ans,cnt);
                SS = res;
                add.clear();
            }
            cnt = 1;
            res.clear();
        }
    }
    vector<int>cur;
    for(int i = 0; i < SS.size(); i++){
        cur.push_back(SS[i]);
    }
    for(int i = 0; i < add.size(); i++){
        cur.push_back(add[i]);
    }
    sort(cur.begin(),cur.end());
    printf("%d\n",(int)cur.size());
    for(int i = 0; i < cur.size(); i++){
        printf("%d ",cur[i]);
    }
}
int main(){
    solved();
    return 0;
}

图片说明
思路:
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
不过这里求的是和的不同的个数,我们可以加一个维度表示能否得到这个数字,比如dp[i][j][x]就是(1,1)到(i,j)能不能得到x,true表示可以,false表示不行。转移方程为 dp[i][j][x] |= dp[i - 1][j][(x - a[i][j] + mod) % mod] | dp[i][j - 1][(x - a[i][j] + mod) % mod]。
最后枚举i从0到1e4 + 6找出dp[n][m][i]为真的计数即可。
代码:

#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;

typedef long long int ll;
int a[1000][1000];
bool dp[110][110][20000];
int mod = 1e4 + 7;
int n,m;
void solved(){
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            scanf("%d",&a[i][j]);
            a[i][j] %= mod;
        }
    }
    dp[1][1][a[1][1]] = true;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            for(int m = 0; m < mod; m++){
                if(i - 1 >= 1)
                dp[i][j][m] |= dp[i - 1][j][(m - a[i][j] + mod) % mod];
                if(j - 1 >= 1)
                dp[i][j][m] |= dp[i][j - 1][(m - a[i][j] + mod) % mod];
            }
        }
    }
    int ans = 0;
    for(int i = 0; i < mod; i++){
        if(dp[n][m][i])ans++;
    }
    cout<<ans<<endl;
}
int main(){
    solved();
}

图片说明
思路:暴力模拟(偷懒了不想写了参考了一下别人的代码)
代码:

#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<set>
#include<stack>
using namespace std;

typedef long long int ll;
const int maxn = 2e6 + 10;
char s[maxn];
int n;
int i;
ll dfs(){
    ll ans = 0,num = 0;

    for(; i <= n;i++){
        ll cnt = 0;
        while(i <= n && isdigit(s[i])) cnt = cnt * 10 + (s[i] - '0'),i++;
        ans += num * (cnt > 0 ? cnt : 1);
        num = 0;

        if(isalpha(s[i])){
            num = (s[i] - 'A' + 1);
        }else if(s[i] == '('){
            i++;
            num = dfs();
        }else break;


    }
    ans += num;
    return ans;
}
int main(){
    scanf("%s",s + 1);
    n = strlen(s + 1);
    i = 1;
    cout<<dfs()<<endl;
    return 0;
}