uva Alberta Collegiate Programming Contest 2011 总结

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=13&page=show_contest&contest=297


最近来看我博客的实在是太少了,当然评论也就更少了,上一个评论还是去年的事,还是我同学评的,囧

周六的时候,也就是4月7号,周六晚上我弄的并不是很认真,我队友他们也没有兴趣,最后的结果就是,我们3个题,当然这个结果我还是比较认同的。

最近喜欢上做套题了,莫名其妙,哎,今天老师还夸了我几句,高兴,但是我知道,我的水平还是有限的,我还得继续努力!加油,come on!嘻嘻

额,我敲了好久,莫名奇妙的弄没了,fuck,懂了,我不应该敲那么多的东东的 简短点

Problem A - Bits and Pieces 思路:判断每一位的情况,然后是第一个不确定的为a为1 b为0 其他位恰好相反,ok最简单的一题

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

int a[40];
int main()
{
    int t;
    cin >> t;
    int c,d;
    while( t-- )
    {
        cin >> c >> d;
        bool re = 1;;int len = 0;
        while(c || d)
        {
            if((d&1) == 1 && (c&1) == 1) a[len] = 1;
            else if((d&1) == 1 && (c&1) == 0) a[len] = 2;
            else if((d&1) == 0 && (c&1) == 1) {re = 0;break;}
            else if((d&1) == 0 && (c&1) == 0) a[len] = 0;
            len++;
            c = c>>1;
            d = d>>1;
        }
        if(re == 0) cout << "-1\n";
        else
        {
            bool first = 0;
            int aa = 0,bb = 0;
            for(int i = len-1;i >= 0;i--)
                if(a[i] == 1)
                {
                    aa = aa*2+1; bb = bb*2+1;
                }else if(a[i] == 0)
                {
                    aa *= 2; bb *= 2;
                }else
                {
                    if(first == 0)
                    {
                        aa = aa*2+1;bb = bb*2;
                        first = 1;
                    }else
                    {
                        aa = aa*2;bb = bb*2+1;
                    }
                }
            cout << bb << " " << aa << "\n";
        }
    }
    return 0;
}
Problem C - How Many... in 3D! 这个题如果你弄过二维的那个填充的问题的话,你就会想到递推公式,然后解决

这个问题的递推公式是:dp[i] = 2*dp[i-1] + 5*dp[i-2] + 4*dp[i-3] + 4*dp[i-4] + 4*dp[i-5] + ... + 4*dp[0];

ok,这个这个就这么解决了,当然做的时候,三维的东西弄了好久

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

const long long P = 1000000007;
long long dp[1000010];
long long re[1000010];
long long re42[1000010];
int main()
{
    dp[0] = 1;
    dp[1] = 2;
    dp[2] = 9;
    dp[3] = 32;

    re[0] = 1;
    re[1] = 3;
    re[2] = 12;
    re[3] = 44;

    for(int i = 4;i < 1000004;i++)
    {
        dp[i] = (dp[i-1]*2 + dp[i-2]*5 + re[i-3]*4)%P;

        re[i] = (re[i-1] + dp[i])%P;
    }
    int t;
    cin >> t;
    while( t-- )
    {
        int n;
        scanf("%d",&n);
        cout << dp[n] << "\n";
        //printf("%I64d\n",dp[n]);
    }
    return 0;
}
 

ok,进入第三题:

Problem D - Pieces and Bits 这个题其实和格雷码有关 当然格雷码大家应该会求吧,不会百度,呵呵,然后就是这个题和格雷码的不同,这个题要求的相邻两个编码应该是有且只有一个相同,ok,我就把偶数位的每一位进行了变化,0->1 1->0;遗憾的是,这个变换之后为什么仍然是1-n的序列,我还是没弄明白,要是有人能弄明白,教教我


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

int code[30];
int code2[30];

void gray2(int len,int n)
{
    memset(code,0,sizeof(code));
    for(int i = 0;i < len;i++)
        if(( n & (1<<i)) != 0)
            code[i] = 1;
    code2[len-1] = code[len-1];
    for(int i = len-2;i >= 0;i--)
        code2[i] = code[i] ^ code[i+1];
}

int main()
{
    int n,t;
    cin >> t;
    while(t--)
    {
        cin >> n;
        for(int i = 0;i < (1<<n);i++)
        {
            gray2(n,i);
            int re = 0;

            if(i % 2 == 0) for(int j = n-1;j >= 0;j--)  code2[j] = 1-code2[j];
            //for(int j = n-1;j >= 0;j--) cout << code2[j];
            for(int j = n-1;j >= 0;j--) re = re * 2 + code2[j];
            printf("%d\n",re);
        }
    }
    return 0;
}

下一个我做出来的题是: Problem E - Casino Advantage 这个题是概率,其实就是递推的概率,不是很难吧,这套题难道我的是读题,赛后看了看这个题,不是很难!!
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

struct note
{
    long long a,b;
}dp[200][200];

long long gcd(long long a,long long b)
{
    while(b)
    {
        long long t=a%b;
        a=b;b=t;
    }
    return a;
}

note add(note a,note b)
{
    note re;
    re.b = a.b*b.b;
    re.a = a.a*b.b + b.a*a.b;
    long long d = gcd(re.a,re.b);

    re.a = re.a / d;
    re.b = re.b / d;
    return re;
}
note mul(note a,note b)
{
    note re;
    re.a = a.a * b.a;
    re.b = a.b * b.b;
    long long d = gcd(re.a,re.b);

    re.a = re.a/d;
    re.b = re.b/d;
    return re;
}
int main()
{
    //cout << gcd(1,0) << " " << gcd(0,1);
    int t;
    cin >> t;
    while(t--)
    {
        int n,m,k;
        n = 140;
        for(int i = 0;i < n;i++)
        {
            for(int j = 0;j < n;j++)
            {
                dp[i][j].a = 0;
                dp[i][j].b = 1;
            }
        }
        dp[0][0].a = 1;
        dp[0][0].b = 1;

        cin >> n >> m >> k;
        for(int i = 1;i <= m;i++)
        {
            for(int j = 0;j <= k;j++)
            {
                note no ;
                no.a = j;no.b = n;
                note yes;
                yes.a = n-j+1;yes.b = n;
                if(j != 0)
                    dp[i][j] = add( mul(dp[i-1][j] , no) , mul(dp[i-1][j-1],yes) );
                else dp[i][j] = mul( dp[i-1][j],no );
            }
        }
        if(dp[m][k].a == 0) cout << "0\n";
        else if(dp[m][k].b == 1) cout << dp[m][k].a << "\n";
        else  cout << dp[m][k].a << "/" << dp[m][k].b << "\n";
    }
    return 0;
}
上面的注意分数加减,还得注意long long ,你懂的
Problem H - Let's call SPaDe a SPaDe 这个是我最后做的题,也是一个没有做出来的题

思路不是很难,我用的是dp加kmp做的,遗憾的是都是wa,wa了好几次,悲哀,如果有人乐意的话,我贴代码,你们瞅瞅,这个代码是wa的!!

我是百思不得其解啊!!

2012年4.12添加,这个题终于a掉了,原因是那个kmp我并没有认真的学习,我队友给我的模板我就套用上了,结果出了一点小差错!!以至于wa了那么久!!

ok,贴一下可以ac的代码!

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

int dp[200];
char str[200];

int next[200];
char dis[200];
void get_next(int n){
    memset(next,0,sizeof(next));
    int i,j=-1;
    next[0]=-1;
    for(i=1;i<=n;i++){     //dis[j]是不是可以理解为i的前一个字符的next值所指想的字符
        while(j>-1&&dis[j+1]!=dis[i])j=next[j];
        if(dis[j+1]==dis[i])j++;
        next[i]=j;
    }
}

int get(int start,int end)//前闭后开
{
    int n = end-start;
    for(int i = 0;i < n;i++) dis[i] = str[start+i];
    dis[n] = '\0';
    get_next(n);
    int l=(n-1)-next[n-1];

    //cout << n << " " << l << "\n";
    if(n% l == 0)
        return n/l;
    else return 1;// 我个大笨蛋居然忘了写这个情况!
}

int getNum(int t)
{
    int re = 0;
    while(t)
    {
        re++;
        t = t / 10;
    }
    return re;
}

int main()
{
    //getNum(11);
    int t;
    //cin >> t;
    scanf("%d",&t);
    //getchar();
    while(t--)
    {
        scanf("%s",str);
        //gets(str);
        int len = strlen(str);
        dp[0] = 0;
        dp[1] = 1;
        for(int i = 2;i <= len;i++)
        {
            dp[i] = 1212000;
            for(int j = 0;j < i;j++)
            {
                int t = get(j,i);//t得到的是重复次数
                int len = i-j;
                int ll = len/t;
                if(  len < ll + 2 + getNum(t)  )
                    dp[i] = min( dp[i],dp[j] + len );
                else
                    dp[i] = min( dp[i],dp[j] + ll + 2 + getNum(t) );
            }
        }
        printf("%d\n",dp[len]);
    }
    return 0;
}



uva上的 这套题,怎么说呢??诡异的地方很多,应该叫trick吧,最后的这个还是没想明白有什么trick

加油!!


你可能感兴趣的:(uva Alberta Collegiate Programming Contest 2011 总结)