多校对抗赛 2015年6月22

总结:

头天晚上饮酒过度,第二天昏昏沉沉的。还好队友比较给力,过了D题的后缀数组(说实话这个数据结构还是第一次听说)I题的计算几何(更偏向思维题的那种)和B题的数学题(矩阵快速幂)。

自己的话。上去过了A题水题,不过手速比较慢,1’14’27时候过的。是一个简单的图遍历,由于数据量不大DFS就能做,时候讨论的时候发现还可以用floyd

最后慢慢熬,把H题熬了出来,不过只是说思路让队友敲,4’58’10。给一个n*n矩阵,n100大小,每个格子上有一个数值。问从第1*1个格子走到n*n个格子,把经过的格子的数值乘起来,得到的数尾0的个数最少多少个。初步思路求出每个格子的25的个数,做出D题的队友说可以分别统计2最少和5最少的情况。想啊想,决定用BFS的做法,一个斜线为一层往下遍历(y-x为定值)。每次遇到一个格子的值比预定值要小时,就用它更新左边和上边的点(上一层相邻的点),然后一直更新下去知道重新回到这条斜线。

赛中的时候E题一直TLE,也没仔细看。赛后过了。首先每个数最多有20多个质因子,因此可以开一个vector来存每个质因子包含的下标是谁。

然而并不够,此题还有一个巨蛋疼的优化,就是初始化每个vector的时候需要进行剪枝。最终优化版本是穷举质因子直到质因子小于等于该数的开方。这时退出,若该数仍然大于1,则说明该数是一个质数,在该数的容器中压入该下标。这样省了很多冗余步骤,不过这个小优化你竟然要T我也是很愤怒的。。。新学函数lower_bound(num,num+cnt,data)。在num数组的0cnt-1的范围中寻找第一个大于等于data的位置,可用于二分查找(这个值-num可以得到它在num数组中的下标)。需要注意的是可能会返回cnt即在数组外,有时候有必要判断一下。

A

#include <cstdio>

#include <cmath>

#include <cstring>

#include <algorithm>

#include <iostream>

#include <queue>

#include <map>

using namespace std;

#define gmax(a,b) a>b?a:b

#define gmin(a,b) a<b?a:b

const int MAXN = 100+5;

int dis[MAXN][MAXN];

queue<int>q1,q2;

int use[MAXN];

int n,m;

int val[MAXN];

int ans;

void bfs(int now)

{

    use[now] = 1;

    q1.push(now);

    q2.push(0);

    while(!q1.empty()){

        int step = q2.front();q2.pop();

        int mark = q1.front();q1.pop();

        for(int i=1; i<=n; i++){

            if(use[i] == 0 && dis[i][mark] == 1){

                use[i] = 1;

                q2.push(step+1);

                q1.push(i);

            }

        }

        ans = gmax(ans, step);

    }

//    if(ff == 1)

//        ans = gmax(ans, step);

}

int main()

{

    int t;

    scanf("%d",&t);

    while(t--){

        scanf("%d%d",&n,&m);

        memset(dis, 0, sizeof(dis));

        memset(use, 0, sizeof(use));

        int le,ri;

        for(int i=0; i<m; i++){

            scanf("%d%d",&le, &ri);

            dis[le][ri] = dis[ri][le] = 1;

        }

        for(int i=1; i<=n; i++){

            ans = 0;

            bfs(i);

            memset(use, 0, sizeof(use));

            val[i] = ans;

        }

        int mmin = 1000;

        int cnt = 0;

        for(int i=1; i<=n; i++){

            if(val[i] == mmin)

                cnt++;

            else if(val[i] < mmin){

                mmin = val[i];

                cnt = 1;

            }

        }

//        printf("val\n");

//        for(int i=1; i<=n; i++)

//            printf("%d ",val[i]);

//        printf("\n");

        printf("%d\n",cnt);

        int ff = 1;

        for(int i=1; i<=n; i++){

            if(val[i] == mmin){

                if(ff)   ff = 0;

                else    printf(" ");

                printf("%d",i);

            }

        }

        printf("\n");

    }

    return 0;

}

 

/**************************************************************

    Problem: 1659

    User: ALPC_T4

    Language: C++

    Result: Accepted

    Time:284 ms

    Memory:1536 kb

****************************************************************/

H题:

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#define  min(a,b)  ((a)<(b)?(a):(b))

using namespace std;

 

typedef struct

{

    int x,y;

}QUE;

 

int dx[4] = {0,1,0,-1},dy[4] = {1,0,-1,0};

int num[1010][1010];

int n,rec[1010][1010],rrr[1010][1010];

bool visit[1010][1010],in[1010][1010];

QUE que[5000010];

 

int Work(int num,int p)

{

    int cnt = 0;

    while(num % p == 0)

    {

        cnt++;

        num = num / p;

    }

    return cnt;

}

 

int BFS()

{

    memset(visit,false,sizeof(visit));

    memset(in,false,sizeof(in));

    int x,y,nx,ny;

    int head = 1,tail = 1;

    que[1].x = 1;   que[1].y =1;

    in[1][1] = visit[1][1] = true;

    rrr[1][1] = rec[1][1];

    while(head <= tail)

    {

        x = que[head].x;

        y = que[head].y;

        head++;

        in[x][y] = false;

        for(int i = 0; i < 4; i++)

        {

            nx = x + dx[i];

            ny = y + dy[i];

            if(nx < 1 || nx > n)    continue;

            if(ny < 1 || ny > n)    continue;

            if(visit[nx][ny] == false)

            {

                tail++;

                que[tail].x = nx;

                que[tail].y = ny;

                rrr[nx][ny] = rrr[x][y] + rec[nx][ny];

                visit[nx][ny] = true;

                in[nx][ny] = true;

            }

            else if(rrr[nx][ny] > rrr[x][y] + rec[nx][ny])

            {

                if(in[nx][ny] == false)

                {

                    tail++;

                    que[tail].x = nx;

                    que[tail].y = ny;

                    in[nx][ny] = true;

                }

                rrr[nx][ny] = rrr[x][y] + rec[nx][ny];

            }

        }

    }

    return rrr[n][n];

}

 

int main()

{

    scanf("%d",&n);

    for(int i = 1; i <= n; i++)

        for(int j = 1; j <= n; j++)

            scanf("%d",&num[i][j]);

    for(int i = 1; i <= n; i++)

        for(int j = 1; j <= n; j++)

            rec[i][j] = Work(num[i][j],2);

    int ans_2 = BFS();

    for(int i = 1; i <= n; i++)

        for(int j = 1; j <= n; j++)

            rec[i][j] = Work(num[i][j],5);

    int ans_5 = BFS();

    int ans = min(ans_2,ans_5);

    printf("%d\n",ans);

}

 

/**************************************************************

    Problem: 1657

    User: ALPC_T4

    Language: C++

    Result: Accepted

    Time:736 ms

    Memory:54492 kb

****************************************************************/

E题:

#include <cstdio>

#include <cmath>

#include <cstring>

#include <string>

#include <algorithm>

#include <iostream>

#include <vector>

using namespace std;

const int MAXN = 1e6+5;

int prime[MAXN],cnt;

int id[MAXN];

int vis[MAXN];

vector<int>dd[MAXN];

void init()

{

    cnt = 0;

    memset(vis, 0, sizeof(vis));

    memset(id, -1, sizeof(id));

    for(int i=2; i<MAXN; i++){

        if(vis[i] == 0){

            vis[i] = 1;

            id[i] = cnt;

            prime[cnt++] = i;

            int now = i*2;

            while(now < MAXN){

                vis[now] = 1;

                now += i;

            }

        }

    }

}

int fi_vec(int mark, int now,int flag)

{

    int le = 0;

    int ri = dd[mark].size() - 1;

    while(le < ri - 1){

        int mid = (le + ri) / 2;

        if(dd[mark][mid] < now)

            le = mid;

        else if(dd[mark][mid] > now)

            ri = mid;

        else if(dd[mark][mid] == now)

            return mid;

    }

    if(dd[mark][le] >= now)

        return le;

    else if(dd[mark][ri] <= now)

        return ri;

    else if(flag == 0)

        return ri;

    else if(flag == 1)

        return le;

}

int fi_prime(int pp)

{

    int le = 0;

    int ri = cnt - 1;

    while(le < ri - 1){

        int mid = (le + ri) / 2;

        if(prime[mid] > pp)

            ri = mid;

        else if(prime[mid] < pp)

            le = mid;

        else if(prime[mid] == pp)

            return mid;

    }

    if(prime[le] == pp)

        return le;

    return ri;

}

int main()

{

    init();

//    printf("max prime is = %d\n",prime[cnt-1]);

    int n,m;

    while(scanf("%d%d",&n,&m) != EOF){

        int temp;

        for(int i=0; i<cnt; i++)

            dd[i].clear();

        for(int i=1; i<=n; i++){

            scanf("%d",&temp);

//            printf("first temp = %d\n",temp);

            for(int j=0;  prime[j]*prime[j]<= temp; j++){

                if(temp % prime[j] == 0){

//                    printf("j = %d,id[j] = %d,temp = %d\n",j,id[j],temp);

                    dd[id[prime[j]]].push_back(i);

                    while(temp % prime[j] == 0)

                        temp /= prime[j];

                }

//                printf("temp = %d\n",temp);

//                if(temp < j)

//                    break;

            }

                if(temp > 1)

            dd[id[temp]].push_back(i);

        }

//        for(int i=0; i<cnt; i++)

//            sort(dd[i].begin(), dd[i].end());

        int le,ri,pp;

        while(m--){

            scanf("%d%d%d",&le,&ri,&pp);

            int mark = id[pp];

//            int mark = lower_bound(prime, prime+cnt, pp) - prime;

//            printf("prime is %d,mark = %d\n",prime[mark],mark);

//            printf("int the vector\n");

//            for(int i=0; i<dd[mark].size(); i++)

//                printf("%d ",dd[mark][i]);

//            printf("\n");

            if(dd[mark].size() == 0 || le > dd[mark][dd[mark].size()-1] || ri < dd[mark][0]){

                printf("0\n");

                continue;

            }

//            int st = lower_bound(dd[mark].begin(),dd[mark].end(),le) - dd[mark].begin();

//            int re  = lower_bound(dd[mark].begin(),dd[mark].end(),ri) - dd[mark].begin();

//            if(re == dd[mark].size() || dd[mark][re] > ri)

//                re--;

//            printf("st = %d, re = %d\n",st,re);

            int st = fi_vec(mark, le, 0);

            int re = fi_vec(mark, ri, 1);

            printf("%d\n",re - st + 1);

        }

    }

    return 0;

}

 B题(自己写赛后)

题目链接:

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1658

题意:

给一个方程Y = (AX + BY)%P,X = Y。求n次运算后得到的Y值。

思路:

矩阵快速幂第一题。

源码:

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <iostream>

#include <queue>

using namespace std;

typedef long long LL;

LL block[2][2];///存储矩阵

LL tblock[2][2];

LL x,y;

void mul1(LL p)

{

    for(int i=0; i<2; i++){

        for(int j=0; j<2; j++){

            tblock[i][j] = 0;

            for(int k=0; k<2; k++)

                tblock[i][j] = (tblock[i][j] + block[i][k] * block[k][j]) % p;///1 1 = 10 * 0 1 + 11 * 11

        }

    }

    for(int i=0; i<2; i++)

        for(int j=0; j<2; j++)

           block[i][j] = tblock[i][j];

}

void mul2(LL p)

{

    LL ans = 0;

    LL t1,t2;

//    printf("before x = %lld, y = %lld\n",x,y);

//    printf("block\n");

//    for(int i=0; i<2; i++){

//        for(int j=0; j<2; j++)

//            printf("%lld ",block[i][j]);

//        printf("\n");

//    }

    t2 = block[0][1] * x % p + block[1][1] * y % p;

    t1 = block[0][0] * x % p + block[1][0] * y % p;

//    printf("t1 = %lld, t2 = %lld\n",t1,t2);

    x = t1 % p;

    y = t2 % p;

//    printf("after x = %lld, y = %lld\n",x,y);

}

int main()

{

    int t;

    scanf("%d",&t);

    for(int cas = 1; cas <= t; cas++){

        LL a,b,p,n;

        scanf("%lld %lld %lld %lld %lld %lld",&x,&y,&a,&b,&p,&n);

//        printf("n = %d\n",n);

        block[0][0] = 0;

        block[0][1] = a;

        block[1][0] = 1;

        block[1][1] = b;

        LL ans = 0;

//        printf("\nblock\n");

//        for(int i=0; i<2; i++){

//            for(int j=0; j<2; j++)

//                printf("%d ",block[i][j]);

//            printf("\n");

//        }

        while(n){

            if(n & 1){

                mul2(p);

            }

            mul1(p);

//            printf("\nblock\n");

//            for(int i=0; i<2; i++){

//                for(int j=0; j<2; j++)

//                    printf("%d ",block[i][j]);

//                printf("\n");

//            }

//            printf("n = %d\n",n);

            n = n >> 1;

        }

        printf("Case #%d: %lld\n",cas,y);

    }

    return 0;

}

/*

0 1  *  0 1 = 1 1

1 1     1 1   1 2

*/

 


你可能感兴趣的:(多校对抗赛 2015年6月22)