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

这次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\n", ((a[2] -a[1]) % mod *(k-1)+a[0]) %mod);
        }else{
            printf("%I64d\n", (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("\n%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\n", 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\n", sum);
            for(int i =0 ;i < sum; i++){
                printf("C %d %d\n", ans[i][0], ans[i][1]);
            }
        }else printf("-1\n");
    }
}
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\n", 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("\n");*/
                        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\n%d\n", 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",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\n", 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\n",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\n", vis[end_x][end_y]);
    }return 0;
}
View Code
posted @ 2015-03-23 19:44  icodefive  阅读(172)  评论(0编辑  收藏  举报