第五届山东理工大学ACM网络编程擂台赛


公共因子

Time Limit: 1000MS Memory limit: 65536K

题目描述

   假设字符串也有因数,一个字符串为s1,然后可以由n个字符串s2来表示,则称s2是s1的因数。
   如“ac”是“acac”的因数。
    给两个字符串,求它们的公因数有多少个。
 

输入

 多组数据,给定两个字符串,s1,s2。长度不超过100000,并且不含空格。
 

输出

 每组数据一行,公因数有多少个。
 

示例输入

acac
ac
aaa
aa

示例输出

1
1


如果要求两个字符串的公共因子,那么它们的公共因子肯定能够被两个字符串整除,所以它们的最长公共因子就是两个串长度最大公约数,长度记为len。然后枚举从1到len,当然也要要求长度能够被两个字符串整除,如果枚举到i长度时,且i能被两个串的长度整除,则将s1的前i个字符存下来,并将串分为len1除以i记为n部分,比较这n部分是否都相同,如果都相同,在将s2的长度len2除以i记为m部分,比较这m部分是否都相同,如果都相同那么前i部分的串即为一个公共因子。

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
char s1[100007],s2[100007];
char ss[100007];
char x1[100007],x2[100007];
int gcd(int x,int y)
{
    if(y==0)return x;
    return gcd(y,x%y);
}
int main()
{
    while(cin>>s1>>s2)
    {
        int len1=strlen(s1);
        int len2=strlen(s2);
        int len=gcd(len1,len2);//欧几里得求最大公约数
        int flag,num=0,cnt,i,j,s,k;
        for(i=1;i<=len;i++)
        {
            flag=0;
            if(len%i==0)//如果是两个串的因数
            {
                for(j=0;j<i;j++)
                    ss[j]=s1[j];//将s1的前i部分存下来
                for(j=i;j<=len1-i;j+=i)//判断分成的n部分是否都相同
                {
                    cnt=0;
                    for(s=j;s<j+i;s++)
                        x1[cnt++]=s1[s];
                    for(k=0;k<i;k++)
                        if(ss[k]!=x1[k])//如果不相同,就结束
                        {
                            flag=1;
                            break;
                        }
                    if(flag)break;
                }
                if(flag)continue;
                for(j=0;j<=len2-i;j+=i)//判断分成的m部分是否都相同
                {
                    cnt=0;
                    for(s=j;s<j+i;s++)
                        x2[cnt++]=s2[s];
                    for(k=0;k<i;k++)
                        if(ss[k]!=x2[k])//如果不相同,就结束
                        {
                            flag=1;
                            break;
                        }
                    if(flag)break;
                }
                if(flag)continue;
                num++;//如果全部相同,则公共因子加1
            }
        }
        printf("%d\n",num);
    }
    return 0;
}


下沉的船

Time Limit: 1000MS Memory limit: 65536K

题目描述

身份优先级: woman = child > man > captain.

多组数据(少于组),每一组有一个整数,代表船上有个人,接下来行,每行有一个名字和他的身份。名字字符长度小于。数据保证不存在重名,注意可能存在多名船长

输出

 输出n行,每一行输出一个名字,先上船的名字在前面。

示例输入

6
Jack captain
Alice woman
Charlie man
Teddy woman
Bob child
Julia woman

示例输出

Alice
Teddy
Bob
Julia
Charlie
Jack

这个题没什么好说的,就是qsort的二重排序。
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
char s[10];
struct sa
{
    int clas,num;
    char name[10];
}chuan[107];

int cmp(const void*_a,const void*_b)
{
	sa*a=(sa*)_a;
	sa*b=(sa*)_b;
    if(a->clas>b->clas)
        return 1;
    else if(a->clas==b->clas)//如果级别相同
    {
        return a->num-b->num;//则返回先输入的
    }
    return -1;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%s %s",chuan[i].name,s);
            if(strcmp(s,"captain")==0)
                chuan[i].clas=3;
            else if(strcmp(s,"man")==0)
                chuan[i].clas=2;
            else chuan[i].clas=1;
            chuan[i].num=i;
        }
        qsort(chuan,n,sizeof(chuan[0]),cmp);
        for(int i=0;i<n;i++)
        {
            printf("%s\n",chuan[i].name);
        }
    }
    return 0;
}



选夫婿1

Time Limit: 1000MS Memory limit: 32768K

题目描述

    倾国倾城的大家闺秀潘小姐要选夫婿啦!武林中各门各派,武林外各大户人家,闻讯纷纷前来,强势围观。前来参与竞选的男生藏龙卧虎,高手云集,才子遍布,帅哥纷纭,更不乏富二代,官二代,可谓声势空前。

    每个人参与竞选的帅哥除了进行一段激情洋溢的求婚演讲以外,还要报上自己姓名、身高和体重,以及个人简历。最后再进行文武选拔,最后夺魁者方能得到潘小姐的芳心。

       潘小姐不爱名利,只看人,第一关就是身高和体重要合格,即必须在其要求的范围内,否则直接排除在外,不允许参加下一轮的选拔。

       作为一个程序员,你没有钱也没有权,擅长的也就是编程了。潘小姐也发现了这一点,所以把首轮根据身高体重进行选拔的任务交给了你,如果完成的好,你可以直接进入下一轮选拔,你笑了。

输入

        潘小姐给你了所有报名男生的信息。输入数据的第一行是一个正整数N(0 < N < 1000)。然后N行数据,每行包含三部分,用空格隔开。第一部分是报名者的姓名name(长度小于20的字符串),然后是整数身高h(0 < h < 300),第三部分是整数体重w (0 < w < 200)。

最后一行是四个整数a,b,c,d.表示身高的合格范围是[a,b],体重的合格范围是[c,d](0 < a < b < 200, 0 < c < d < 300)。

 

输出

        你需要把合格的男生信息按照身高从低到高输出,格式跟输入一样,也是每行三个信息,共N行,如果身高相同则按体重从轻到重输出,若没有合格人选则输出No,具体格式见样例。

 

示例输入

8武大郎 70 40西门庆 180 70李逵 160 150燕青 175 69鲁智深 180 100武松 180 75小泉纯一狼 30 20孙二娘 169 60165 190 60 90

示例输出

孙二娘 169 60燕青 175 69西门庆 180 70武松 180 75

这个题和上面的题差不多,都是qsort排序。
#include<stdio.h>
#include<stdlib.h>
struct sa
{
    char s[77];
    int h,w;
}data[1000];
int cmp(const void*_a,const void*_b)
{
	sa*a=(sa*)_a;
	sa*b=(sa*)_b;
    if(a->h>b->h)
        return 1;
    else if(a->h==b->h)
    {
        return a->w-b->w;
    }
    return -1;
}
int main()
{
    int m;
    scanf("%d",&m);
    for(int a=1;a<=m;a++)
    {
        scanf("%s %d %d",&data[a].s,&data[a].h,&data[a].w);
    }
    int h1,h2,w1,w2,flag=0;

    scanf("%d%d%d%d",&h1,&h2,&w1,&w2);
    qsort(data+1,m,sizeof(data[1]),cmp);
    for(int i=1;i<=m;i++)
	{
	    if(data[i].h>=h1&&data[i].h<=h2&&data[i].w>=w1&&data[i].w<=w2)
	    {
	        printf("%s %d %d\n",data[i].s,data[i].h,data[i].w);
	        flag=1;
	    }

	}
	if(!flag)printf("No\n");
    return 0;
}

图案打印

Time Limit: 1000MS Memory limit: 65536K

题目描述

一年一度的植树节就要到了,计算机学院学生准备在学院教学楼门前的空地上种植树木。为使树木排列得更加美观,大家决定把树木排列成菱形。现在告诉你我们所拥有的树木能排列成边长为N的菱形,请你编程输出树木所排列的图案(用*号代表树木)。

输入

一个整数N(1≤N≤10)。

输出

排列成菱形图案的*号。请注意在图案中:每行树木之间无空行,每列树木之间均有一个空列。

示例输入

3

示例输出

    *
  *   *
*       *
  *   *
    *


这个题没什么好说的,只要仔细点,就能过,不要注意每列树木之间均有一个空列,因为这个,PE了两次。
#include<stdio.h>
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=n; i++)
        {
            if(i==1)
            {
                for(int j=1; j<=2*(n-1); j++)
                    printf(" ");
                printf("*\n");
            }
            else
            {
                for(int j=1; j<=2*(n-i); j++)
                    printf(" ");
                printf("*");
                for(int j=1; j<=2*(i-1); j++)
                    printf(" ");
                for(int j=1; j<2*(i-1); j++)
                    printf(" ");
                printf("*\n");
            }
        }
        for(int i=n-1; i>=1; i--)
        {
            if(i==1)
            {
                for(int j=1; j<=2*(n-1); j++)
                    printf(" ");
                printf("*\n");
            }
            else
            {
                for(int j=1; j<=2*(n-i); j++)
                    printf(" ");
                printf("*");
                for(int j=1; j<=2*(i-1); j++)
                    printf(" ");
                for(int j=1; j<2*(i-1); j++)
                    printf(" ");
                printf("*\n");
            }
        }
    }
    return 0;
}



487-3279

Time Limit: 2000MS Memory limit: 65536K

题目描述

Businesses like to have memorable telephone numbers. One way to make a telephone number memorable is to have it spell a memorable word or phrase. For example, you can call the University of Waterloo by dialing the memorable TUT-GLOP. Sometimes only part of the number is used to spell a word. When you get back to your hotel tonight you can order a pizza from Gino's by dialing 310-GINO. Another way to make a telephone number memorable is to group the digits in a memorable way. You could order your pizza from Pizza Hut by calling their ``three tens'' number 3-10-10-10. 

The standard form of a telephone number is seven decimal digits with a hyphen between the third and fourth digits (e.g. 888-1200). The keypad of a phone supplies the mapping of letters to numbers, as follows: 

A, B, and C map to 2 
D, E, and F map to 3 
G, H, and I map to 4 
J, K, and L map to 5 
M, N, and O map to 6 
P, R, and S map to 7 
T, U, and V map to 8 
W, X, and Y map to 9 

There is no mapping for Q or Z. Hyphens are not dialed, and can be added and removed as necessary. The standard form of TUT-GLOP is 888-4567, the standard form of 310-GINO is 310-4466, and the standard form of 3-10-10-10 is 310-1010. 

Two telephone numbers are equivalent if they have the same standard form. (They dial the same number.) 

Your company is compiling a directory of telephone numbers from local businesses. As part of the quality control process you want to check that no two (or more) businesses in the directory have the same telephone number.

输入

The input will consist of one case. The first line of the input specifies the number of telephone numbers in the directory (up to 100,000) as a positive integer alone on the line. The remaining lines list the telephone numbers in the directory, with each number alone on a line. Each telephone number consists of a string composed of decimal digits, uppercase letters (excluding Q and Z) and hyphens. Exactly seven of the characters in the string will be digits or letters.

输出

Generate a line of output for each telephone number that appears more than once in any form. The line should give the telephone number in standard form, followed by a space, followed by the number of times the telephone number appears in the directory. Arrange the output lines by telephone number in ascending lexicographical order. If there are no duplicates in the input print the line: 

No duplicates.

示例输入

12
4873279
ITS-EASY
888-4567
3-10-10-10
888-GLOP
TUT-GLOP
967-11-11
310-GINO
F101010
888-1200
-4-8-7-3-2-7-9-
487-3279

示例输出

310-1010 2
487-3279 4
888-4567 3

题意是说一些字母可以代表一些数字(除了Q和Z),然后给你一些号码,让你将它转换成000-0000的形式,并判断是否有重复的,如果重复数大于1,则输出,如果一个也没有,则输出No duplicates.
此题可以用map来存储字符串,并来判断个数。

#include<stdio.h>
#include<map>
#include<string.h>
#include<string>
#include<iostream>
using namespace std;
char s[1007],ss[1007];
string z;
int main()
{
    int n;
    scanf("%d",&n);

        map<string,int>mp;
    for(int i=0;i<n;i++)
    {
        scanf("%s",s);
        int len=strlen(s),a=0;
        memset(ss,0,sizeof(ss));
        for(int j=0;j<len;j++)
        {
            if(s[j]=='A'||s[j]=='B'||s[j]=='C')
                ss[a++]='2';
            else if(s[j]=='D'||s[j]=='E'||s[j]=='F')
                ss[a++]='3';
            else if(s[j]=='G'||s[j]=='H'||s[j]=='I')
                ss[a++]='4';
            else if(s[j]=='J'||s[j]=='K'||s[j]=='L')
                ss[a++]='5';
            else if(s[j]=='M'||s[j]=='N'||s[j]=='O')
                ss[a++]='6';
            else if(s[j]=='P'||s[j]=='R'||s[j]=='S')
                ss[a++]='7';
            else if(s[j]=='T'||s[j]=='U'||s[j]=='V')
                ss[a++]='8';
            else if(s[j]=='W'||s[j]=='X'||s[j]=='Y')
                ss[a++]='9';
            else if(s[j]>='0'&&s[j]<='9')
                ss[a++]=s[j];
            if(a==3)
                ss[a++]='-';
            //printf("%c",ss[a]);
        }
        //printf("\n");
        z=ss;
        mp[z]++;
    }
    int max=1,flag=0;
    map<string,int>::iterator it;
    for(it=mp.begin();it!=mp.end();it++)
    {
        if(max<it->second)
        {
            flag=1;
            cout<<it->first<<" "<<it->second<<endl;

        }
    }
    if(!flag)
    printf("No duplicates.\n");
    return 0;
}


The area

Time Limit: 1000MS Memory limit: 32768K

题目描述

Ignatius bought a land last week, but he didn't know the area of the land because the land is enclosed by a parabola and a straight line. The picture below shows the area. Now given all the intersectant points shows in the picture, can you tell Ignatius the area of the land?
 Note: The point P1 in the picture is the vertex of the parabola. 
 

输入

The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case contains three intersectant points which shows in the picture, they are given in the order of P1, P2, P3. Each point is described by two floating-point numbers X and Y(0.0<=X,Y<=1000.0).

输出

For each test case, you should output the area of the land, the result should be rounded to 2 decimal places.

示例输入

2
5.000000 5.000000
0.000000 0.000000
10.000000 0.000000
10.000000 10.000000
1.000000 1.000000
14.000000 8.222222

示例输出

33.33
40.69

提示

hdoj1071 有链接提示的题目请先去链接处提交程序,AC后提交到SDUTOJ中,以便查询存档。 For float may be not accurate enough, please use double instead of float.

来源

Ignatius.L

模拟积分。可以根据顶点式求出抛物线的方程,y=a*(x-x1)+y1.然后根据另外两个点可以求出直线方程。然后用抛物线方程减去直线方程得到一个二次函数方程,分别求出二次函数的A,B,C,然后根据二重积分求面积。即最后方程式是:s=1/3*A*(X3*X3*X3-X2*X2*X2)+1/2*B*(X3*X3-X2*X2)+C*(X3-X2)。

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

int main()
{
    int t;
    double x1,y1,x2,y2,x3,y3;
    scanf("%d",&t);
    while(t--)
    {
     scanf("%lf%lf",&x2,&y2);
     scanf("%lf%lf",&x1,&y1);
     scanf("%lf%lf",&x3,&y3);

     double a=(y3-y2)/((x3-x2)*(x3-x2));
     double h=x2;
     double p=y2;
     double k=(y3-y1)/(x3-x1);
     double b=y3-k*x3;
     double A=a;
    // printf("%lf\n",A);
     double B=-2*h*a-k;
     //printf("%lf\n",B);
     double C=p-b+a*h*h;
      //printf("%lf\n",C);
     double s=1./3*A*(x3*x3*x3-x1*x1*x1)+1./2*B*(x3*x3-x1*x1)+C*(x3-x1);
     printf("%.2f\n",s);
    }
    return 0;
}

GCC

Time Limit: 1000MS Memory limit: 65536K

题目描述

The GNU Compiler Collection (usually shortened to GCC) is a compiler system produced by the GNU Project supporting various programming languages.  But it doesn’t contains the math operator “!”.

In mathematics the symbol represents the factorial operation. The expression n! means "the product of the integers from 1 to n". For example, 4! (read four factorial) is 4 × 3 × 2 × 1 = 24. (0! is defined as 1, which is a neutral element in multiplication, not multiplied by anything.)

We want you to help us with this formation: (0! + 1! + 2! + 3! + 4! + ... + n!)%m. 

输入

The first line consists of an integer T, indicating the number of test cases.

Each test on a single consists of two integer n and m. 

0 < T <= 20
0 <= n < 10 100 (without leading zero) 
0 < m < 1000000 

输出

Output the answer of (0! + 1! + 2! + 3! + 4! + ... + n!)%m. 

示例输入

1 10 861017 

示例输出

593846

提示


如果m为7,n为10的话,那么(0!+1!+2!+...+10!)%7=(0!%7+1!%7+2!%7+...+9!%7+10!%7)%7因为从7往后7!和8!和9!和10!都包含*7这项,所以它们%7都为0,因此得出结论,如果n大于m,那么只要算n小于m的部分即可。另外山理工好像不识别%I64d,我换成%lld就过了。

#include<stdio.h>
#include<string.h>
char s[107];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        long long m,ans=1,count=1;
        scanf("%s%lld",&s,&m);
        int len=strlen(s);
        long long number=0;
        if(len>7)
        {
            number=m-1;
        }
        else
        {
            for(int i=0; i<len; i++)
            {
                number=number*10+(s[i]-'0');
            }
        }
        if(number>=m)
            number=m-1;
        for(int i=1; i<=number; i++)
        {
            count=(i*count)%m;
            ans=(ans+count)%m;
        }
        printf("%lld\n",ans%m);
    }
    return 0;
}

图形密码

Time Limit: 1000MS Memory limit: 65536K

题目描述

触屏手机上的图形密码是一种简单有效的安全措施,有利于保护我们的隐私。小明新买了一台触屏手机,对手机上的图形密码很感兴趣,仔细研究了图形密码的构成,发现图形密码的构成连线方向可以分为顺时针和逆时针两类,有人喜欢顺时针滑动手指解码,有人喜欢逆时针解码,有人会交替两种方向。小明想做个调查,他需要记录解码连线的方向,打算通过编程来完成这个任务,你能帮助他吗? 

输入

第一行输入一个数T代表测试数据个数(T<=500)。每个测试样例第一行有一个n代表有序点对个数。接下来1行n对x,y,分别代表一个点对。(1<=x,y<=6  1<=n<=100)
 

输出

连线的方向为顺时针(clockwise),还是逆时针(counterclockwise),如果方向发生变化,则输出变化前的方向,变化点的坐标和变化后的方向。比如上图所示的密码锁的解码方向为:clockwise (2,2)  counterclockwise 使用空格分开,不同的项。每行输出一个结果。
 

示例输入

3
5
1 1 2 1 3 1 3 2 3 3
8
1 1 1 2 1 3 2 3 3 3 3 2 3 1 2 1
7
1 1 1 2 1 3 2 2 3 1 3 2 3 3

示例输出

counterclockwise
clockwise
clockwise (3,1) counterclockwise

提示

 

来源

 中国海洋大学第三届“朗讯杯”编程比赛高级组试题


一开始以为这道题就是枚举每条横边和每条竖边,然后分情况讨论,但是写起来相当麻烦而且还实现不了。因此叉积的概念出现了,譬如线段AB和线段AC,它们的叉积是AB*AC,如果>0的话,那么AC在AB的逆时针方向即夹角为逆时针方向;如果<0的话,那么AC在AB的顺时针方向,即夹角为顺时针。如果等于0的话,AB和AC在同一条直线上。
#include<stdio.h>
int x[107],y[107];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,flag1=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&x[i],&y[i]);
        for(int i=2;i<=n-1;i++)
        {
            int flag=0;
            int x1=x[i+1]-x[i];
            int y1=y[i+1]-y[i];
            int x2=x[i-1]-x[i];
            int y2=y[i-1]-y[i];
            if(x1*y2-x2*y1<0)
                flag=1;
            else if(x1*y2-x2*y1>0)
                flag=2;
            if(flag1==0)
                flag1=flag;
            if(flag1&&flag&&flag1!=flag)
            {
                if(flag1==1)
                    printf("clockwise (%d,%d) ",x[i],y[i]);
                else if(flag1==2)
                    printf("counterclockwise (%d,%d) ",x[i],y[i]);
                flag1=flag;
            }
        }
        if(flag1==1)
            printf("clockwise\n");
        else
            printf("counterclockwise\n");
    }
}

France \'98

Time Limit: 1000MS Memory limit: 65536K

题目描述

Today the first round of the Soccer World Championship in France is coming to an end. 16 countries are remaining now, among which the winner is determined by the following tournament:

 1 Brazil -----+	
   	       +-- ? --+
 2 Chile ------+       |
		       +-- ? --+
 3 Nigeria ----+       |       |
	       +-- ? --+       |
 4 Denmark ----+	       |
	                       +-- ? --+
 5 Holland ----+	       |       |
	       +-- ? --+       |       |
 6 Yugoslavia -+       |       |       |
		       +-- ? --+       |
 7 Argentina --+       |	       |
	       +-- ? --+	       |
 8 England ----+		       |
				       +-- World Champion
 9 Italy ------+		       |
	       +-- ? --+	       |
10 Norway -----+       |               |
		       +-- ? --+       |
11 France -----+       |       |       |
	       +-- ? --+       |       |
12 Paraguay ---+	       |       |
			       +-- ? --+
13 Germany ----+	       |
	       +-- ? --+       |
14 Mexico -----+       |       |
		       +-- ? --+
15 Romania ----+       |
	       +-- ? --+
16 Croatia ----+
For each possible match A vs. B between these 16 nations, you are given the probability that team A wins against B. This (together with the tournament mode displayed above) is sufficient to compute the probability that a given nation wins the World Cup. For example, if Germany wins against Mexico with 80%, Romania against Croatia with 60%, Germany against Romania with 70% and Germany against Croatia with 90%, then the probability that Germany reaches the semi-finals is 80% * (70% * 60% + 90% * 40%) = 62.4%.

Your task is to write a program that computes the chances of the 16 nations to become the World Champion \'98.

输入

The input file will contain just one test case.
The first 16 lines of the input file give the names of the 16 countries, from top to bottom according to the picture given above. 
Next, there will follow a 16 x 16 integer matrix P where element pijgives the probability in percent that country #i defeats country #j in a direct match. Country #i means the i-th country from top to bottom given in the list of countries. In the picture above Brazil is #1 and Germany is #13, so p1,13=55 would mean that in a match between Brazil and Germany, Brazil wins with a probability of 55%. 
Note that matches may not end with a draw, i.e. pij + pji = 100 for all i,j.

输出

Output 16 lines of the form "XXXXXXXXXX p=Y.YY%", where XXXXXXXXXX is the country\'s name, left-justified in a field of 10 characters, and Y.YY is their chance in percent to win the cup, written to two decimal places. Use the same order of countries like in the input file.

示例输入

Brazil
Chile
Nigeria
Denmark
Holland
Yugoslavia
Argentina
England
Italy
Norway
France
Paraguay
Germany
Mexico
Romania
Croatia
50 65 50 60 55 50 50 65 45 55 40 55 40 55 50 50 
35 50 35 45 40 35 35 50 30 40 25 40 25 40 35 35 
50 65 50 60 55 50 50 65 45 55 40 55 40 55 50 50 
40 55 40 50 45 40 40 55 35 45 30 45 30 45 40 40 
45 60 45 55 50 45 45 60 40 50 35 50 35 50 45 45 
50 65 50 60 55 50 50 65 45 55 40 55 40 55 50 50 
50 65 50 60 55 50 50 65 45 55 40 55 40 55 50 50 
35 50 35 45 40 35 35 50 30 40 25 40 25 40 35 35 
55 70 55 65 60 55 55 70 50 60 45 60 45 60 55 55 
45 60 45 55 50 45 45 60 40 50 35 50 35 50 45 45 
60 75 60 70 65 60 60 75 55 65 50 65 50 65 60 60 
45 60 45 55 50 45 45 60 40 50 35 50 35 50 45 45 
60 75 60 70 65 60 60 75 55 65 50 65 50 65 60 60 
45 60 45 55 50 45 45 60 40 50 35 50 35 50 45 45 
50 65 50 60 55 50 50 65 45 55 40 55 40 55 50 50 
50 65 50 60 55 50 50 65 45 55 40 55 40 55 50 50 

示例输出

Brazil     p=8.54%
Chile      p=1.60%
Nigeria    p=8.06%
Denmark    p=2.79%
Holland    p=4.51%
Yugoslavia p=7.50%
Argentina  p=8.38%
England    p=1.56%
Italy      p=9.05%
Norway     p=3.23%
France     p=13.72%
Paraguay   p=3.09%
Germany    p=13.79%
Mexico     p=3.11%
Romania    p=5.53%
Croatia    p=5.53%

提示


来源

1998/99 University of Ulm Local Contest

题意:题目只有一个case,有16个球队,给出名字,并且下面一个16*16的矩阵,p[i][j]是一个二位的整数,表示i球队打败j球队的概率,p[i][j]+p[j][i]=100,下面16行输出球队名字并且后面一个百分率是该球队获得总冠军的概率

DP递推或者记忆化搜索都可以

设dp[i][left][right]表示i这个球队在第left到第right球队里面得到冠军的概率,所以最后需要的是dp[i][1][16]。一个球队要在当面的阶段得到冠军必须在之前得到冠军

所以mid=(left+right)/2;  

i和j在[left,right]里面争夺冠军(例如i和j在1到16里面争夺冠军,也就是争夺总冠军),那么i和j必定是来自于两个分区的

left<=i<=mid , 那么需要得到dp[i][left][mid],dp[j][mid+1][right] 

mid+1<=i<=right,那么需要得到dp[i][mid+1][right] , dp[j][left][mid]



#include<stdio.h>
#include<string.h>
double dp[17][17][17],s[17][22];
char n[17][77];
int main()
{
    for(int i=1;i<=16;i++)
    {
        scanf("%s",n[i]);
        //printf("%s\n",s[i]);
    }

    double ss;
    for(int i=1;i<=16;i++)
        for(int j=1;j<=16;j++)
        {
            scanf("%lf",&ss);
            s[i][j]=ss/100;
            //printf("%lf",s[i][j]);
        }

    memset(dp,0,sizeof(dp));
    for(int i=1;i<=16;i++)
        dp[i][i][i]=1;
    int left,mid,right;
    for(int i=2;i<=16;i*=2)
    {
        for(left=1;left<=16;left+=i)
        {
            right=left+i-1;
            mid=(left+right)/2;
            for(int j=left;j<=mid;j++)
                for(int k=mid+1;k<=right;k++)
                {
                    dp[j][left][right]+=s[j][k]*dp[j][left][mid]*dp[k][mid+1][right];
                    dp[k][left][right]+=s[k][j]*dp[j][left][mid]*dp[k][mid+1][right];
                }
        }
    }
    for(int i=1;i<=16;i++)
        printf("%-10s p=%.2f%%\n",n[i],dp[i][1][16]*100);
    return 0;
}



魔幻数字47

Time Limit: 1000MS Memory limit: 32768K

题目描述

数字47一向被数学界的人认为是很魔幻的一个数字,和47有关的任务被认为是魔幻任务。现在有一个简单的魔幻任务,给定a和b,打印所有在 以a,b为端点的闭区间 中最后两位为47的整数,你能一次AC吗??

输入

第一行为一个整数n,表示有多少组测试数据。(n <= 100)
第2-n+1行,每行两个整数,分别代表a,b。(a,b <= 10000)

输出

对于每组输入,输出在以a,b为端点的闭区间内且最后两位为47的整数,如果有多个,则从小到大排序输出;若一个都没有,则输出NONE。

示例输入

2
1 147
1 2

示例输出

47
147
NONE

提示


来源

moon

找出第一个最后两位是47的数字,然后输出每次+100的数字即可,另外输入的a不一定比b小,因为这个WA了一次。
#include<stdio.h>
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        while(n--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int tmp;
            if(a>b)
            {
                tmp=a;
                a=b;
                b=tmp;
            }
            int flag=0;
            for(int i=a; i<=b; i++)
            {
                if(flag==0)
                {
                    int j=i;
                    int c=j%10;
                    j/=10;
                    int d=j%10;
                    if(c==7&&d==4)
                    {
                        flag=1;
                        printf("%d\n",i);
                        i+=99;
                    }
                }
                else
                {
                    printf("%d\n",i);
                    i+=99;
                }
            }
            if(!flag)
                printf("NONE\n");
        }
    }
    return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值