• 大二第一次东北团队训练赛


    这次A的题全是亮哥敲的,丧失也出了不少思路,基本就我在躺,得让自己的思路和代码能力迅速提高起来,尽自己最大的力量吧。

    比赛后又敲了一遍。

    A.给前三个数求第k项,需判断是等差还是等比数列。

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    const long long mod = 200907;
    long long a[4];
    long long sort_pow(long long k, long long m){
        if(k == 0)
            return 1;
        if(k % 2){
            long long uu = sort_pow(k/2, m);
            return (uu*uu*m) % mod;
        }else{
            long long uu = sort_pow(k/2, m);
            return (uu*uu) % mod;
        }
    }
    int main(){
        long long t;
        scanf("%I64d", &t);
        while(t--){
            for(long long i = 0; i < 3; i++){
                scanf("%I64d", &a[i]);
            }
            long long k;
            scanf("%I64d", &k);
            if(a[2] - a[1] == a[1] - a[0]){
                printf("%I64d
    ", ((a[2] -a[1]) % mod *(k-1)+a[0]) %mod);
            }else{
                printf("%I64d
    ", (a[0] * sort_pow(k-1,a[1]/a[0]))% mod);
            }
        }
    
    }
    View Code

    B.两种操作

    M a b。把a所在的堆放到b所在的堆上面。

    C a:问a下面有多少箱子

    就是带权并查集,不过好久没敲代码了,敲得又慢bug又多,最后还是星星重构了一遍过了

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    const int maxa = 30005;
    int fa[maxa];
    int val[maxa];
    int up_box[maxa];
    int find(int i){
        if(i == fa[i]){
            return i;
        }
        find(fa[i]);
        val[i] += val[fa[i]];
        return fa[i] = fa[fa[i]];
    
    }
    void add(int x, int y){
        int fx = find(x);
        int fy = find(y);
        int upx = up_box[fx];
        int upy = up_box[fy];
        if(fx != fy){//printf("*");
            fa[fx] = upy;
            val[fx] = 1;
            up_box[fy] = upx;
        }
    }
    int main(){
        int n;
        while(scanf("%d", &n)!=EOF){
            for(int i = 1; i < maxa; i++){
                fa[i] = i;
                val[i] = 0;
                up_box[i] = i;
            }
            while(n--){
                char c;
                scanf("
    %c", &c);
                if(c == 'M'){
                    int a, b;
                    scanf("%d%d", &a, &b);
                    add(a, b);
                }else{
                    int a;
                    scanf("%d", &a);
                    find(a);
                    printf("%d
    ", val[a]);
                }
            }
            /*for(int i = 1; i <= 6; i++){
                find(i);
                printf("%d ", val[i]);
            }*/
        }
    }
    View Code

    C.每次能把两行或者两列互换,只换列就可以,如果某一列第x个位置是1,那么他就可以和x建立一个联系,如果只换列不可以的话换行也是不行的,将列想成是男人,行想成是女人,如果换行的话说明两个女人调换了,那么对能否能够全部匹配上并没有影响,并查集模板。

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<vector>
    using namespace std;
    const int maxa = 104;
    int mp[maxa][maxa];
    vector<int>g[maxa];
    int from[maxa], tot;
    bool use[maxa];
        int n;
    bool match(int x){
        for(int i = 0;i  < g[x].size(); i++){
            if(!use[g[x][i]]){
                use[g[x][i]] = true;
                if(from[g[x][i]] == -1 || match(from[g[x][i]])){
                    from[g[x][i]] = x;
                    return true;
                }
            }
        }
        return false;
    }
    int hunger(){
        tot = 0;
        memset(from, 255, sizeof(from));
        for(int i = 1; i <= n; i++){
            memset(use, 0, sizeof(use));
            if(match(i))
                ++tot;
        }
        return tot;
    }
    int main(){
        while(scanf("%d", &n)!=EOF){
            for(int i = 1; i <= n; i++) g[i].clear();
            for(int i = 0; i < n; i++){
                for(int k = 0;k  < n; k++){
                    scanf("%d", &mp[i][k]);
                }
            }
            for(int i = 0; i < n; i++){
                for(int k = 0; k <n ; k++){
                    if(mp[k][i]){
                        g[k+1].push_back(i+1);
                    }
                }
            }
            if(hunger() == n){
                int sum = 0;
                int ans[maxa][2];
                int m = n;
                while(m--)
                for(int i = 1; i <= n; i++){
                    if(from[i] != i){
                        int a = ans[sum][0] = i;
                        int b = ans[sum++][1] = from[i];
                        swap(from[a], from[b]);
                    }
                }
                printf("%d
    ", sum);
                for(int i =0 ;i < sum; i++){
                    printf("C %d %d
    ", ans[i][0], ans[i][1]);
                }
            }else printf("-1
    ");
        }
    }
    View Code

    D.给出n个数,形成队列必须两两之差不大于k,问有多少种情况。

    亮哥思路每次从1到n依次往里面插,插m的时候找出m-1时的所有种情况,比m-k小的全用"_" 表示,每次状态都会减一,思路吊的不行。

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<map>
    #include<vector>
    using namespace std;
    const int maxa = 55;
    #define LL long long
    vector<LL> v[maxa];
    map<LL, LL> mp[maxa];
    const int mod = 1000000007;
    LL pow[20];
    int  make_numb(LL x, LL num[], LL cut[]){
        int o =0;
        LL xx = x;
        LL uu = 0;
        while(xx){
            num[o] = xx%10;
            xx /= 10;
            uu+=pow[o]*num[o];
            cut[o] = uu;
            o++;
        }
        return o;
    }
    LL comp(LL num[], int o, int i, int m){
       /* printf("%d
    ", i);
        cout<<"===="<<endl;
        for(int i = o -1; i >= 0; i--){
            cout<<num[i];
        }puts("");*/
        LL u = 0;
        if(i<= m+1){
            for(int i = o-1; i >= 0; i--){
                u = u*10+num[i];
            }
            return u;
        }//printf("******");
        for(  int i = 0;i < o; i++){
            if(num[i] != 1)
                num[i] --;
        }
       /* cout<<"===="<<endl;
        for(int i = o -1; i >= 0; i--){
            cout<<num[i];
        }puts("");*/
        LL uu = num[o-1];
        for(int i = o-2; i >= 0; i--){
            if(num[i] == num[i+1] && num[i] == 1){
                continue;
            }
            uu = uu * 10 + num[i];
        }
        //cout<<uu<<endl;
        return uu;
    }
    int main(){
        int n, m;
        pow[0] = 1;
        for(int i = 1; i< 20; i++){
            pow[i] = pow[i-1]*10;
        }
        LL num1[20], cut1[20];
        LL num[20], cut[20];
        while(scanf("%d%d", &n, &m)!=EOF){
            for(int i = 0; i <= n+2; i++){
                v[i].clear();
                mp[i].clear();
            }
            if(m == 0){
                v[2].push_back(1);
                mp[2][1] = 1;
            }
            else{
                v[2].push_back(2);
                mp[2][2] = 1;
            }
            for(int i = 3; i <= n+1; i++){
                //cout<<"i=="<<i<<endl;
                for(int j = 0; j < v[i-1].size(); j ++){
                    int o = make_numb(v[i-1][j], num, cut);
                    int ii = min(i, m+2);
    
                    for(int k = 0; k <= o; k++){
                    //cout<<"**"<<v[i-1][j]<<endl;
                        LL u = -1;
                        if(k == 0 ){
                            if(num[k] != 1)
                                u = ii + v[i-1][j]*10;
                                //cout<<"qian"<<u<<endl;
                        }else if(k == o){
                            if(num[k-1] != 1)
                                u = v[i-1][j] + ii*pow[o];
    
                                //cout<<"hou"<<u<<endl;
                        }else{
                            if(num[k]!= 1 &&num[k-1] != 1){
                                u = cut[k-1] +10*(v[i-1][j] -cut[k-1])+ pow[k]*ii;
                            }
                                //cout<<"zhong"<<u<<" "<<cut[k-1]<<" "<<v[i-1][j] -cut[k-1]<<endl;
                        }
                        if(u != -1){
                            int oo = make_numb(u, num1, cut1);
                            /*for(int j = 0; j < oo; j++){
                                cout<<num1[j];
                            }printf("
    ");*/
                            u = comp(num1, oo, i, m);
                            //cout<<"u == "<<u<<endl;
                            if(!mp[i][u]){
                                v[i].push_back(u);
                            }
                            mp[i][u] += mp[i-1][v[i-1][j]];
                            mp[i][u] %= mod;
                        }
                    }
                }//cout<<"<<"<<endl;3
                /*for(int k = 0; k < v[i].size(); k++){
                    cout<<v[i][k]<<" " <<mp[i][v[i][k]]<<endl;
                }*/
            }
            //cout<<endl;
            LL ans = 0;
            for(int i = 0; i < v[n+1].size(); i++){
                //cout<<v[n+1][i]<<" "<<mp[n+1][v[n+1][i]]<<endl;;
                ans += mp[n+1][v[n+1][i]];
                ans %= mod;
            }
            cout<<ans<<endl;
        }
    }
    View Code

    E。所有人都没敢做,结果就是个暴力深搜,优化都不用

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    const int maxa = 30;
    char str[maxa][maxa];
    int mp[maxa][maxa];
    int ans[maxa*maxa];
    int Move[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
    int o, n, m;
    int anser[4] = {'D','U', 'R', 'L'};
    int judge(int x, int y){
        if(0 <= x && x < n && 0 <= y && y < m){
            return 1;
        }return 0;
    }
    int dfs(int ax, int ay, int x, int y, int sum){
        if(sum == 0){
            printf("%d
    %d
    ", ax, ay);
            for(int i = 0;i < o; i++){
                printf("%c", anser[ans[i]]);
            }puts("");
            return 1;
        }
        for(int i = 0; i < 4; i++){
            int vx = Move[i][0];
            int vy = Move[i][1];
            int xx = x + vx;
            int yy = y + vy;
            if(judge(xx, yy) && mp[xx][yy]==0){
                while(1){
                    xx += vx;
                    yy += vy;
                    if(judge(xx, yy)){
                        if(mp[xx][yy]){
                            int s = sum;
                            int v = mp[xx][yy];
                            int vv = mp[xx+vx][yy+vy];
                            mp[xx][yy] = 0;
                            mp[xx+vx][yy+vy] += v-1;
                            if(judge(xx + vx, yy+ vy)){
                                sum --;
                            }else{
                                sum -= v;
                            }
                            ans[o++] = i;
                            if(dfs(ax, ay, xx, yy, sum)){
                                return 1;
                            }
                            o--;;
                            mp[xx][yy] = v;
                            mp[xx+vx][yy+vy] = vv;
                            sum = s;
                            break;
                        }
                    }else
                        break;
                }
            }
        }
        return 0;
    }
    int main(){
        while(scanf("%d%d", &m, &n)!=EOF){
            for(int i = 0; i < n; i++){
                scanf("%s", str[i]);
            }
            int sum = 0;
            for(int i = 0;i < n; i++){
                for(int k = 0; k < m ; k++){
                    if(str[i][k] =='.'){
                        mp[i][k]  = 0;
                    }else{
                        mp[i][k] = str[i][k] - 'a' +1;
                    }
                    sum += mp[i][k];
                }
            }
            int ok = 0;
            o =  0;
            for(int i = 0; i < n; i++){
                for(int k = 0; k < m; k++){
                    if(mp[i][k] == 0){
                        if(dfs(i, k, i, k, sum)){
                            ok = 1;
                            break;
                        }
                    }
                }
                if(ok) break;
            }
        }
    }
    /*
    25 25
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    .........................
    .........................
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaa
    */
    View Code

    H.赤裸裸欧拉函数模板

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    const int maxa = 3000005;
    int minDiv[maxa], phi[maxa];//, sum[maxa];
    void genphi(){
        for(int i = 1; i < maxa; i++){
            minDiv[i] = i;
        }
        for(int i = 2; i * i < maxa; i++){
            if(minDiv[i] ==i){
                for(int j = i*i; j < maxa; j += i){
                    minDiv[j] = i;
                }
            }
        }
        phi[1] = 1;
        for(int i = 2; i < maxa; i++){
            phi[i] = phi[i/minDiv[i]];
            if((i/minDiv[i]) % minDiv[i] == 0){
                phi[i] *= minDiv[i];
            }else{
                phi[i] *= minDiv[i] - 1;
            }
        }
    }
    int main(){
        int a, b;
        genphi();
        while(scanf("%d%d", &a, &b)!=EOF){
            long long anser = 0;
            for(int i = a; i <= b; i++){
                    anser+= phi[i];
            }
            cout<<anser<<endl;
        }
    }
    View Code

     G.给出m个单词,求长度为n的字符串里包含k个单词的字符串有多少种情况,ac自动机加状压dp

    dp[i][j][k]表示长度为i再自动机中的节点为j时包含k种字符有多少情况

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int MOD = 20090717;
    int n, m, k;
    int dp[30][110][1<<10];
    int num[5000];
    struct Tire{
        int next[110][26], fail[110], end[110];
        int root, L;
        int newnode(){
            for(int i = 0; i < 26; i++){
                next[L][i] = -1;
            }
            end[L++] = 0;
            return L-1;
        }
        void init(){
            L = 0;
            root = newnode();
        }
        void insert(char buf[], int id){
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++){
                if(next[now][buf[i] - 'a'] == -1)
                    next[now][buf[i]-'a'] = newnode();
                now = next[now][buf[i]-'a'];
            }
            end[now] |= (1<<id);
        }
        void build(){
            queue<int>Q;
            fail[root] = root;
            for(int i = 0; i < 26; i++){
                if(next[root][i] == -1)
                    next[root][i] = root;
                else{
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while(!Q.empty()){
                int now = Q.front();
                Q.pop();
                end[now] |= end[fail[now]];
                for(int i = 0; i < 26; i++){
                    if(next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else{
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                    }
                }
            }
        }
        int solve(){
            for(int i = 0; i <= n; i++){
                for(int j = 0; j < L; j ++){
                    for(int p = 0; p < (1<<m); p++){
                        dp[i][j][p] = 0;
                    }
                }
            }
            dp[0][0][0] = 1;//printf("*");
            for(int i = 0; i < n; i++)
                for(int j = 0; j < L; j++)
                    for(int p = 0; p < (1<<m); p++)
                        if(dp[i][j][p] > 0){
                            for(int x = 0; x < 26; x++){
                                int newi = i+1;
                                int newj = next[j][x];
                                int newp = (p|end[newj]);
                                //printf("%d %d %d %d
    ",n, i, j, p);
                                dp[newi][newj][newp] += dp[i][j][p];
                                dp[newi][newj][newp] %= MOD;
                            }
                        }
            int ans = 0;
            for(int p = 0; p < (1<<m); p ++){
                if(num[p] < k) continue;
                for(int i = 0; i < L; i++){
                    ans = (ans + dp[n][i][p])%MOD;
                }
            }
            return ans;
        }
    };
    char buf[20];
    Tire ac;
    int main(){
        for(int i = 0; i < (1<<10); i++){
            num[i] = 0;
            for(int j = 0; j < 10; j++)
                if(i & (1<<j))
                    num[i]++;
        }
        while(scanf("%d%d%d", &n, &m, &k)!=EOF){
            if(n==0 && m==0 && k == 0)
                return 0;
            ac.init();
            for(int i = 0;i  < m; i++){
                scanf("%s", buf);
                ac.insert(buf, i);
            }
            ac.build();
            printf("%d
    ", ac.solve());
        }
    }
    View Code

    F。广搜

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<queue>
    using namespace std;
    const int maxa = 1105;
    char str[maxa][maxa];
    int vis[maxa][maxa];
    int n, m;
    int str_x, str_y, end_x, end_y;
    struct point{
        int x, y, vis;
        bool operator < (const point& a) const {
            return a.vis < vis;
        }
    };
    int Move[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
    int judge(int x, int y){
        if(0 <= x && x < n && 0 <= y && y < m && vis[x][y] == -1){
            return 1;
        }return 0;
    }
    priority_queue<point>q;
    int ok;/*
    int dfs(int x, int y, int u){
        if(ok)return 1;
        if(judge(x,y) && str[x][y] == 'X'){
            vis[x][y] = u;
            q.push(point{x,y, u});
            for(int i = 0; i < 4; i++){
                dfs(x+Move[i][0], y+Move[i][1], u);
            }
        }
        if(x == end_x && y == end_y) ok = 1;
    
    }*/
    int bfs(){
        ok = 0;
        while(!q.empty())q.pop();
        memset(vis, -1, sizeof(vis));
        vis[str_x][str_y] = 0;
        q.push(point{str_x, str_y, 0});
        while(!q.empty()){
            point New = q.top(); q.pop();
            if(ok == 1)
                break;
           // printf("%d %d
    ",New.x, New.y);
            for(int i = 0; i < 4; i++){
                int xx = New.x+Move[i][0];
                int yy = New.y + Move[i][1];
                if(!judge(xx, yy))continue;
                if(str[xx][yy] == '.'){
                    vis[xx][yy] = vis[New.x][New.y]+1;
                    q.push(point{xx, yy,vis[xx][yy]});
                }else{
                    vis[xx][yy] = vis[New.x][New.y];
                    q.push(point{xx,yy,vis[xx][yy]});
                }
            }
        }
    }
    int main(){
        //freopen("in.cpp", "r", stdin);
        while(scanf("%d%d", &n, &m)!=EOF){
            if(n== 0 && m == 0)break;
            for(int i = 0;i < n; i++){
                scanf("%s", &str[i]);
            }
            scanf("%d%d%d%d", &str_x, &str_y, &end_x, &end_y);
            str_x--,str_y--,end_x--,end_y--;
            bfs();
            printf("%d
    ", vis[end_x][end_y]);
        }return 0;
    }
    View Code
  • 相关阅读:
    CF786E ALT
    CF704D Captain America
    [NOI2016]循环之美
    「PKUWC2018」猎人杀
    [HNOI2019]JOJO
    博客已转移
    $20200203$的数学作业
    20200202的数学作业
    NOIp 2016 选课 (DP)
    Luogu P2574 XOR的艺术 (线段树)
  • 原文地址:https://www.cnblogs.com/icodefive/p/4360809.html
Copyright © 2020-2023  润新知