http://www.bnuoj.com/bnuoj/contest_show.php?cid=3743#info

 

A

按照给定的表的顺序判断一下输出就可以了。。。

#include <iostream>
#include <cstdio>
using namespace std;
int main(){
    int T,x;
    scanf("%d",&T);
    while (T--){
        scanf("%d", &x);
        if (x == 1 || x == 5 || x == 6)
            puts("Unknown");
        else{
            if(x==11 || x==12)
                puts("Basic Training");
            if(x==12)
                puts("Rookie Contest");
            if(x>=2 && x<=4)
                puts("Spring Training");
            if(x==4)
                puts("BNU Contest");
            if(x==7)
                puts("Practice Week");
            if(x==7 || x==8)
                puts("Summer Training");
            if(x>=9 && x<=11)
                puts("Regional Contest");
        }
    }
}

B

f[i][j] 表示i桶油能不能走j的距离

状态转移方程

f[i][j]=f[i][j]||f[i-1][j-a[s]];

#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
int T,l,x,n;
int f[5][1050];
int a[1050];
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&l,&x,&n);
        l-=x;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        if(l<0){
            printf("No\n");
            continue;
        }
        memset(f,0,sizeof(f));
        f[0][0]=1;
        for(int s=1;s<=n;s++){
            for(int i=1;i<=4;i++)
                for(int j=a[s];j<=l;j++){
                    f[i][j]=f[i][j]||f[i-1][j-a[s]];
                }
        }

        if(f[4][l]==1)
            printf("Yes\n");
        else
            printf("No\n");
    }

}

C 能被操作的次数就是L跟H能整除2的次数之和。判一下奇偶即可。

#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
int T,l,x,n;
int f[5][1050];
int a[1050];
int main(){
    scanf("%d",&T);
    while(T--){
        int L,H;
        scanf("%d%d",&L,&H);
        int sum=0;
        while(L%2==0)
            L/=2,sum++;
        while(H%2==0)
            H/=2,sum++;
        if(sum%2==0)
            puts("Adivon prevails");
        else
            puts("Adidas loses");

    }
}

D

trie树 记录每个节点的个数与长度,dfs求解 

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

int n,m;
char a,b;
int trie[200010][30],cnt[200010],sum[200010];


char c[100010];

int sz,ans;
void insert(){
    cout<<endl<<endl;
    int cur=0;
    int len=strlen(c);
    for(int i=0;i<len;i++){
        //cout<<c[i]<<endl;
        cout<<cur<<endl;
        if(!trie[cur][c[i]-'a']){
            trie[cur][c[i]-'a']=++sz;

        }
        sum[cur]+=len-i-1;
        cnt[cur]++;////////////
        cur=trie[cur][c[i]-'a'];
    }
    //cout<<cur<<endl;
}

void init(){
    memset(trie,0,sizeof(trie));
    memset(cnt,0,sizeof(cnt));
    memset(sum,0,sizeof(sum));
    sz=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf(" %s",c);
        insert();
        int len=strlen(c);
        for(int j=0,w=len-1;j<len/2;j++,w--){
            char tmp;
            tmp=c[j];
            c[j]=c[w];
            c[w]=tmp;
        }
        insert();
    }
    int ans=0;
    cout<<endl;
    for(int i=0;i<=sz;i++){
        printf("%d %d\n",cnt[i],sum[i]);
        ans+=(cnt[i]-1)*sum[i];
    }
    cout<<ans<<endl;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        init();
    }
}

 

每一步期望获得的分数显然等于上一步获得分数加一,然后乘上概率p。最后将每一步期望的分数相加。

#include <cstdio>
#include <iostream>
using namespace std;
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int l;
        double p,tmp=0,ans=0;
        scanf("%d%lf",&l,&p);
        for(int i=1;i<=l;i++){
            tmp=(tmp+1)*p;
            ans+=tmp;
        }
        printf("%.6lf\n",ans);
    }
}

 

 

H  期望 1/(p*(1-p))

#include <iostream>
#include <cstdio>
using namespace std;
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        double p;
        scanf("%lf",&p);
        printf("%.2lf\n",1/(p*(1-p)));
    }
}

 J f[i][0] 表示没用过忍术 f[i][1] 表示开始用第一次忍术 f[i][2] 表示结束了第一次忍术 f[i][3]开始用第二次忍术 f[i][4] 表示结束了第二次忍术

#include <cstdio>
#include <iostream>
using namespace std;
int a[10010],c,n,f[10010][5];
int Max(int a,int b){
    return a>b?a:b;
}
int main(){
    scanf("%d%d",&c,&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    f[0][0]=c;
    f[0][1]=-0x7fffffff;
    f[0][2]=-0x7fffffff;
    f[0][3]=-0x7fffffff;
    f[0][4]=-0x7fffffff;
    for(int i=1;i<=n;i++){
        f[i][0]=f[i-1][0];
        if(f[i][0]-a[i]>=0)
            f[i][1]=Max(f[i-1][1],f[i][0]-a[i]);
        else
            f[i][1]=f[i-1][1];
        f[i][2]=Max(f[i-1][2],f[i-1][1]+a[i]);
        if(f[i][2]-a[i]>=0)
            f[i][3]=Max(f[i-1][3],f[i][2]-a[i]);
        else
            f[i][3]=f[i-1][3];
        f[i][4]=Max(f[i-1][4],f[i-1][3]+a[i]);
    }
    int ans=-0x7fffffff;
    for(int i=0;i<=4;i++){
        ans=Max(ans,f[n][i]);
    }
    cout<<ans<<endl;
}

 k  矩阵快速幂优化一个递推关系。

递推关系如下。

#include <cstdio>
#include <iostream>
using namespace std;

double f[1010*1010][21];
int main(){

    int T;
    scanf("%d",&T);
    while(T--){
        int n,m,k,s;

        scanf("%d%d%d%d",&n,&m,&k,&s);
        if(n==1){
            printf("0.5000\n");
            continue;
        }
        f[0][s]=1;
        for(int i=1;i<=m*k;i++){
            for(int j=1;j<=n;j++){
                if(j==1){
                    f[i][j]=f[i-1][2]*0.5;
                    printf("%d %d %lf\n",i,j,f[i][j]);
                    continue;
                }
                if(j==n){
                    f[i][j]=f[i-1][n-1]*0.5;
                    printf("%d %d %lf\n",i,j,f[i][j]);
                    continue;
                }

                if(j==2){
                    f[i][j]=f[i-1][1]+f[i-1][j+1]*0.5;
                    printf("%d %d %lf\n",i,j,f[i][j]);
                    continue;
                }
                if(j==n-1){
                    f[i][j]=f[i-1][n]+f[i-1][j-1]*0.5;
                    printf("%d %d %lf\n",i,j,f[i][j]);
                    continue;
                }
                f[i][j]=f[i-1][j-1]*0.5+f[i-1][j+1]*0.5;
                printf("%d %d %lf\n",i,j,f[i][j]);
            }
        }
        for(int i=1;i<=n;i++){
            cout<<f[m*k][i]<<endl;
        }

    }
}

 

矩阵优化如下

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>

#define SIZE 30

using namespace std;

class MATRIX
{
    public:
    double mt[SIZE][SIZE];
    int x,y;
    friend MATRIX operator *(MATRIX &a,MATRIX &b){
        MATRIX c;
        memset(c.mt,0,sizeof c.mt);
        c.x=a.x; c.y=b.y;
        for(int i=1;i<=a.x;i++)
            for(int j=1;j<=b.y;j++)
                for(int k=1;k<=a.y;k++)
                    c.mt[i][j]=(c.mt[i][j]+(a.mt[i][k])*(b.mt[k][j]));
        return c;
    }
    friend void print(MATRIX &a){
        cout<<a.x<<' '<<a.y<<endl;
        for(int i=1;i<=a.x;i++){
            for(int j=1;j<=a.y;j++)
                printf("%.2lf ",a.mt[i][j]);
            printf("\n");
        }
    }
    friend MATRIX power(MATRIX a, int b){
        MATRIX ans;
        ans.x=a.x,ans.y=a.y;
        for(int i=1;i<=ans.x;i++)
            for(int j=1;j<=ans.y;j++){
                if(i==j)
                    ans.mt[i][j]=1;
                else
                    ans.mt[i][j]=0;
            }
        for (; b; b >>= 1)
        {
            if (b & 1) ans = ans * a;
            a = a * a;
        }
        return ans;
    }

}ans,M1,M;

int n;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        int n,m,k,s;

        scanf("%d%d%d%d",&n,&m,&k,&s);
        if(n==1){
            printf("1.0000\n");
            continue;
        }
        M1.x=M1.y=n;
        for(int i=1;i<=n;i++){
            if(i==1){
                M1.mt[1][2]=1;
                continue;
            }
            if(i==n){
                M1.mt[n][n-1]=1;
                continue;
            }
            M1.mt[i][i+1]=M1.mt[i][i-1]=0.5;
        }
        M.x=1,M.y=n;
        M.mt[1][s]=1;
        ans=power(M1,m*k);
        ans=M*ans;
        for(int i=1;i<n;i++)
            printf("%.4lf ",ans.mt[1][i]);
        printf("%.4lf\n",ans.mt[1][n]);

    }
}

 

I  折半查找 (待做。。

L 判断出直线与矩阵的交点分条件讨论(待做。