【noip2008普及】传球游戏

题目描述

上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。

游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同学可以把球传给自己左右的两个同学中的一个(左右任意),当老师再次吹哨子时,传球停止,此时,拿着球没有传出去的那个同学就是败者,要给大家表演一个节目。

聪明的小蛮提出一个有趣的问题:有多少种不同的传球方法可以使得从小蛮手里开始传的球,传了m次以后,又回到小蛮手里。两种传球方法被视作不同的方法,当且仅当这两种方法中,接到球的同学按接球顺序组成的序列是不同的。比如有三个同学1号、2号、3号,并假设小蛮为1号,球传了3次回到小蛮手里的方式有1->2->3->1和1->3->2->1,共2种。

输入输出格式

输入格式:
输入文件ball.in共一行,有两个用空格隔开的整数n,m(3<=n<=30,1<=m<=30)。

输出格式:
输出文件ball.out共一行,有一个整数,表示符合题意的方法数。

输入输出样例

输入样例#1: 复制
3 3
输出样例#1: 复制
2
说明

40%的数据满足:3<=n<=30,1<=m<=20

100%的数据满足:3<=n<=30,1<=m<=30

2008普及组第三题

#include
#include
using namespace std;
const int mod=10007;
int n,zhan0[50000],zhan1[50000],top0,top1,topop=0;
char ch[100000],op[50000];

inline int read()
{
    int now=0,f=1; char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9')
    {
        now=(now<<1)+(now<<3)+ch-'0';
        ch=getchar();
    }
    return now*f;
}

void write(int x)
{
    if (x<0) {putchar('-'); x=-x;}
    if (x>=10) write(x/10);
    putchar(x%10+'0');
}

int level(char ch)
{
    switch (ch)
    {
        case '+':return 1; break;
        case '*':return 2; break;
        case '(':return 0; break;
    }
}

void calc(char ch)
{
    switch (ch)
    {
        case '+':
            {
                int sh0=zhan0[top0]%mod*zhan0[top0-1]%mod;//乘号写成了加号 
                int sh1=zhan0[top0-1]%mod*zhan1[top1]%mod+zhan1[top1-1]%mod*zhan0[top0]%mod+zhan1[top1-1]%mod*zhan1[top1]%mod;
                zhan0[--top0]=sh0%mod; zhan1[--top1]=sh1%mod;
                break;
            }
        case '*':
            {
                int sh1=zhan1[top1]%mod*zhan1[top1-1]%mod;
                int sh0=zhan0[top0-1]%mod*zhan1[top1]%mod+zhan1[top1-1]%mod*zhan0[top0]%mod+zhan0[top0-1]%mod*zhan0[top0]%mod;
                zhan0[--top0]=sh0%mod; zhan1[--top1]=sh1%mod;
                break;
            }
    }

}

void push_num()//加入数字1 
{
    zhan0[++top0]=1; zhan1[++top1]=1;
}

int main()
{
    n=read();
    for (int i=1; i<=n; i++)
        scanf("%c",&ch[i]);
    ch[0]='('; ch[++n]=')';
    int i=0;
    while (i<=n)
    {
        if (ch[i]==' ') {i++; continue;}
        else if (ch[i]=='(') {op[++topop]='('; if (ch[i+1]!='(') push_num();}//括号左边放一个,右边放一个 
        else if (ch[i]==')'){
            if (op[topop]=='(') topop--;
            while (op[topop]!='(') calc(op[topop--]);
            topop--;//减去左括号 
        }
        else if (level(op[topop])>=level(ch[i]))//忘记了level,一定要细心!
        {
            while (level(op[topop])>=level(ch[i])) calc(op[topop--]);
            op[++topop]=ch[i];
            push_num();
        }
        else if (level(op[topop])if (ch[i+1]!='(') push_num();
        }
        i++;
    }
    write(zhan0[1]%mod);
    return 0;
}

你可能感兴趣的:(dp,noip真题,环形dp,区间dp,栈)