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;
}

 

举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
原文地址:https://www.cnblogs.com/AbandonZHANG/p/2613718.html