ACdream群训练赛(46)

A.Seinfeld

http://acm.hdu.edu.cn/showproblem.php?pid=3351

用num来标记次数,用len来表示 { 的个数 从前开始遍历字符串,如果是 { 就不配对 ,len++,如果是 } 且如果len不为0就len--,在此情况下如果len为零了,就只能将此字符变成 { ,那么num++;遍历完了,如果len不为0就说明剩下了 { 没有配对 此时只需要 num+=len/2即可;

View Code
#include <fstream>

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <iomanip>

#include <iomanip>

#include <climits>

#include <vector>

#include <stack>

#include <queue>

#include <list>

#include <set>

#include <map>

#include <algorithm>

#include <string>

#include <cstring>



using namespace std;



int n0,n1,n2,n3,n4;



int main()

{

    string s;

    int i,k,num,len;

    for(k=1;;k++)

    {

        cin>>s;

        if(s[0]=='-')

        break;

        num=0;

        len=0;

        for(i=0;i<s.size();i++)

        {

            if(s[i]=='{')

            len++;

            else

            {

                if(len)

                len--;

                else

                {

                    num++;

                    s[i]='{';

                    len=1;

                }

            }

        }

        if(len>0)

        num+=len/2;

        cout<<k<<'.'<<' '<<num<<endl;

    }

    return 0;

}

 

B.Tiles of Tetris, NOT!

http://acm.hdu.edu.cn/showproblem.php?pid=3352

 

就是问最少用多少个矩形能拼成一个面积最小的正方形。num=最小公倍数/a*最小公倍数/b。

View Code
#include <fstream>

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <iomanip>

#include <iomanip>

#include <climits>

#include <vector>

#include <stack>

#include <queue>

#include <list>

#include <set>

#include <map>

#include <algorithm>

#include <string>

#include <cstring>



using namespace std;



int gcd(int a,int b)

{

    int c;

    if(a==0)  return b;

    while(b!=0) c=b,b=a%b,a=c;

    return a;

}

int main()

{

    long long a,b;

    while(cin>>a>>b)

    {

        if(a==0&&b==0)  break;

        int c=gcd(a,b);

        long long d=a*b/c/c;

        cout<<d<<endl;

    }

    return 0;

}

 

C.Not So Flat After All

http://acm.hdu.edu.cn/showproblem.php?pid=3353

分别把两个数分解质因数为p1^a1*p2^a2......的形式。维度就是两个数需要的所有素数,距离就是两个数所有质因数的a1、a2...的差的和。

View Code
#include <fstream>

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <iomanip>

#include <iomanip>

#include <climits>

#include <vector>

#include <stack>

#include <queue>

#include <list>

#include <set>

#include <map>

#include <algorithm>

#include <string>

#include <cstring>



using namespace std;



#define MAX 1000000



int noprime[MAX];

int pp[2][MAX];

int numm[MAX];       //出现几个素数

int numnum;

int vis[MAX];

int b[2];



int Max(int a,int b)    {   return a>b?a:b;  }

int Min(int a,int b)    {   return a<b?a:b;  }



void Prime(int n)        //筛法求素数

{

    int k;

    noprime[0]=noprime[1]=1;

    noprime[2]=0;

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

        if (!noprime[i])

        {

            k=i;

            while(k+i<n)

            {

                k=k+i;

                noprime[k]=1;

            }

        }

}



void find_prime_factor(int n)

{

    int k=b[n];

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

        if (!noprime[i])

        {

            if (k%i==0)

            {

                if (!vis[i])

                {

                    vis[i]=numnum+1;

                    numm[numnum]=i;

                    numnum++;

                }

                while (k%i==0)

                {

                    k/=i;

                    pp[n][vis[i]-1]++;

                }



            }

        }

    return;

}



int main()

{

    int caseo=1;

    Prime(1000000);

    while(cin>>b[0]>>b[1])

    {

        if (b[0]==0 && b[1]==0)

            return 0;

        memset(pp,0,sizeof(pp));

        memset(numm,0,sizeof(numm));

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

        numnum=0;

        find_prime_factor(0);

        find_prime_factor(1);

        cout<<caseo++<<". "<<numnum<<":";

        int ans=0;

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

        {

            ans+=abs(pp[0][i]-pp[1][i]);

        }

        cout<<ans<<endl;

    }





    return 0;

}

 

D.Probability One

http://acm.hdu.edu.cn/showproblem.php?pid=3354

简单题,模拟即可。

View Code
#include <fstream>

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <iomanip>

#include <iomanip>

#include <climits>

#include <vector>

#include <stack>

#include <queue>

#include <list>

#include <set>

#include <map>

#include <algorithm>

#include <string>

#include <cstring>



using namespace std;



int n0,n1,n2,n3,n4;



int main()

{

    int caseo=1;

    while(cin>>n0,n0)

    {

        n1=n0*3;

        if (n1%2==1)

            n2=(n1+1)/2;

        else

            n2=n1/2;

        n3=3*n2;

        n4=n3/9;

        if (n1%2==1)

        {

            string s="odd";

            cout<<caseo++<<". "<<s<<" "<<n4<<endl;

        }

        else

        {

            string s="even";

            cout<<caseo++<<". "<<s<<" "<<n4<<endl;

        }



    }





    return 0;

}

 

G.Stock Chase(难)

http://acm.hdu.edu.cn/showproblem.php?pid=3357

// 【题意】
// 有N个公司,A公司可以买B公司的股票
// B公司可以买C公司的股票,如此A公司会间接持有C公司的股票
// 只要A公司直接或者间接持有了X公司的股票,X公司就不能购买A公司的股票,这种操作非法
// 按照时间顺序给出T次购买请求,问有多少次非法的购买请求会被回绝

// 【思路】
// 传递闭包
// 每个query后加入一条边,计算新的传递闭包
// 由于每次query前,G都是一个传递闭包,所以可以直接看是否有逆向弧来判断是否query合法

// 时间复杂度肉眼看是O(T*N*N),T是查询次数,N是节点数
// 理论上铁超时,但是实际上G很快会达到一种“饱和”的状态,大部分的query都是马上得到结果

View Code
#include <fstream>

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <iomanip>

#include <iomanip>

#include <climits>

#include <vector>

#include <stack>

#include <queue>

#include <list>

#include <set>

#include <algorithm>

#include <string>

#include <cstring>



using namespace std;



#define MAXN       235



bool conn[MAXN][MAXN];

std::vector<int> vconn[MAXN];

int N, T;



int main()

{

       int kase = 1;



       int i, k;

       int v;

       for (i = 1; i <= MAXN; i++)

              vconn[i].reserve(MAXN);



       while (scanf("%d %d", &N, &T), N || T) {

              memset(conn, 0, sizeof(conn));

              for (i = 1; i <= N; i++) {

                     // 注意有自己到自己的弧,这样做是为了方便算传递闭包,算之前应该对i==i做特判

                     vconn[i].resize(0);

                     vconn[i].push_back(i);

                     conn[i][i] = true;

              }



              int a, b;

              int res = 0;

              while (T--) {

                     scanf("%d %d", &a, &b);

                     if (a == b || conn[b][a]) {

                            res ++;

                            continue;

                     }



                     if (conn[a][b])

                            continue;



                     for (i = 1; i <= N; i++) {

                            // 没有到a的弧或者已经有到b的弧

                            if (!conn[i][a] || conn[i][b])

                                   continue;



                            // 到a有弧,到b没弧

                            for (k = vconn[b].size()-1; k >= 0; k--) {

                                   v = vconn[b][k];

                                   if (conn[i][v])

                                          continue;



                                   conn[i][v] = true;

                                   vconn[i].push_back(v);

                            }

                     }

              }



              printf("%d. %d\n", kase++, res);

       }



       return 0;

}

 

K.Hex-a-bonacci

http://lightoj.com/volume_showproblem.php?problem=1006

这道题挺有意思的。如果直接复制代码(刚开始就以为是这样一道用来搞笑的题。。。)递归fn重复计算太多要超时,把它放到数组里存起来就好了

View Code
#include <fstream>

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <iomanip>

#include <iomanip>

#include <climits>

#include <vector>

#include <stack>

#include <queue>

#include <list>

#include <set>

#include <map>

#include <algorithm>

#include <string>

#include <cstring>



using namespace std;



int a, b, c, d, e, f;

int ffn[10005];

int fn( int n ) {

    if( n == 0 ) return a;

    if( n == 1 ) return b;

    if( n == 2 ) return c;

    if( n == 3 ) return d;

    if( n == 4 ) return e;

    if( n == 5 ) return f;

    return( ffn[n-1] + ffn[n-2] + ffn[n-3] + ffn[n-4] + ffn[n-5] + ffn[n-6] );

}

int main() {

    int n, caseno = 0, cases;

    scanf("%d", &cases);

    while( cases-- ) {

        scanf("%d %d %d %d %d %d %d", &a, &b, &c, &d, &e, &f, &n);

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

            ffn[i]=fn(i)% 10000007;

        printf("Case %d: %d\n", ++caseno, ffn[n] % 10000007);

    }

    return 0;

}

 

 

你可能感兴趣的:(cd)