HDU P11

2099 整除的尾数

一个整数,只知道前几位,不知道末二位,被另一个整数除尽了,那么该数的末二位该是什么呢?
思路解析: 就是说输入一个被除数 a (这是差两位的数),输入一个除数b,能够整除,现在让你还原这个数。
利用的就是 从0到99循环,加在a上与b做%得到的是不是整数,是的话就输出出来。

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int main()
{
  	int a,b;
	  while(scanf("%d %d",&a,&b)&&a||b) //必须a b 都存在
	  {
	  	a=a*100;
	  	int k=0;
	  	for(int i=0;i<=99;i++)
	  	{
	  		if((a+i)%b==0)
	  		{
	  			k++;
	  			if(k==1)
	  			{
	  			if(i<10)
	  			{	
				  printf("0");
	  			  printf("%d",i);	
				  }
	  			else
	  			printf("%d",i);
				  }
				else
				{
				if(i<10)
	  			{
	  			printf(" 0");
	  			printf("%d",i);
				  }
				  else
				printf(" %d",i);
				}
			  }
		  }
		  printf("\n");
	   } 
    return 0;}

2098分拆素数和

把一个偶数拆成两个不同素数的和,有几种拆法呢?

//遍历一个数判断是否是素数,循环只要到这个数开根号就行。

 #include <stdio.h>
#include <math.h>
int is_prime(int n)
{
	int i, k = sqrt(n);
	for(i = 2; i <= k; i++)
		if(n % i == 0)
			return 0;
	return 1;
}
int main()
{
	int n, i, count, j;
	while(~scanf("%d", &n), n)
	{
		count = 0;
		j = n / 2;
		for(i = 2; i < j; i++)
			if(is_prime(i) && is_prime(n-i))
				count++;
		printf("%d\n", count);
	}
	return 0;
}  
  • i+ n-i =n 用for循环从2开始暴力遍历所有的情况

2097 Sky数

Sky从小喜欢奇特的东西,而且天生对数字特别敏感,一次偶然的机会,他发现了一个有趣的四位数2992,这个数,它的十进制数表示,其四位数字之和为2+9+9+2=22,它的十六进制数BB0,其四位数字之和也为22,同时它的十二进制数表示1894,其四位数字之和也为22,啊哈,真是巧啊。Sky非常喜欢这种四位数,由于他的发现,所以这里我们命名其为Sky数。但是要判断这样的数还是有点麻烦啊,那么现在请你帮忙来判断任何一个十进制的四位数,是不是Sky数吧。

  • 用进制转化的方法 不管是什么进制的数
#include <stdio.h>
int sum(int n,int base)
{
	int sum;
	while (n>0)
	{
        sum+=n%base;
        n/=base;
	}
	return sum;
}
int main()
{
	int n,a,b,c;
	while (scanf("%d",&n)&&n!=0)
	{
		a=sum(n,10);b=sum(n,12);c=sum(n,16);
       if (a==b&&a==c&&b==c)
       {
		   printf("%d is a Sky Number.\n",n);
       }
	   else
	   {
		   printf("%d is not a Sky Number.\n",n);
	   }
	}
}

2096 小明A+B

小明今年3岁了, 现在他已经能够认识100以内的非负整数, 并且能够进行100以内的非负整数的加法计算.
对于大于等于100的整数, 小明仅保留该数的最后两位进行计算, 如果计算结果大于等于100, 那么小明也仅保留计算结果的最后两位.

例如, 对于小明来说:

  1. 1234和34是相等的
  2. 35+80=15

给定非负整数A和B, 你的任务是代表小明计算出A+B的值.

  • 利用模除 100 不管是大于100的数还是小于100的数都可以。

      #include<stdio.h>
      int main()
      {
        int n,a,i,b;
        scanf("%d",&n);
        {
          for(i=1;i<=n;i++)
       {
        int sum=0;
         scanf("%d%d",&a,&b);
          a%=100;
           b%=100;
           sum=a+b;
            sum%=100;
          printf("%d\n",sum);
       }
        }
          return 0;
          }
    

    2095 find your present (2)

首先想到的是水桶算法,利用数组,但是这道题的时间复杂度不能够接受

整数的异或是先把它们化成二进制,再按位异或。
比如3^5,3=011,5=101,两数按位异或后为110,即6。
几个数异或满足交换律。2^ 3^ 2=2^ 2 ^ 3=0^3=3.
两个相同的数异或为0,普通数都出现了偶数次,
所以它们异或后都是0,而0与那个特别数异或后还是那个特殊数。

	#include<stdio.h>
	int main()
	{
	    int n,i,x,y;
	    while(scanf("%d",&n)!=EOF&&n)
	    {
	           x=0;
	           while(n--)
	           {
	                scanf("%d",&y);
	                x^=y;     
	           }         
	           printf("%d\n",x);             
	    }
	    return 0;
	}

2094 产生冠军 待看

分析:这道题求的是获胜者,前面都是获胜者,后面的都是失败者,如果前面的字符在后面能找到,那么前面的就是失败者,输入用两个数组a,b,另外一个数组a1存的是获胜者
如果最后只剩一个名字,说明有冠军,否则没有冠军

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{
   int n;
   string a[1050],b[1050];
   string a1[1050];              
   int vis[1050];
  while(cin>>n)
  {
      if(n==0)
        break;
      getchar();
      memset(vis,0,sizeof(vis));       
      for(int i=0;i<n;i++)
        cin>>a[i]>>b[i];
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(a[i]==b[j])
                    vis[i]++;
            }
        }
        int count=0;
        for(int i=0;i<n;i++)
        {
            if(vis[i]==0)            //标记为0的说明是获胜者
            {
                a1[count++]=a[i];   //a1里面存的是获胜者
            }
        }
 
        for(int i=0;i<count;i++)
        {
            if(a1[i]==a1[i+1])
            {
                for(int j=i;j<count;j++)
                {
                    a1[j]=a1[j+1];               //去掉相同的名字
                }
                i--;
                count--;
            }
        }
        if(count==1)
            printf("Yes\n");
        else
            printf("No\n");
  }
  return 0;
}

2093 考试排名

C++编程考试使用的实时提交系统,具有即时获得成绩排名的特点。它的功能是怎么实现的呢?
我们做好了题目的解答,提交之后,要么“AC”,要么错误,不管怎样错法,总是给你记上一笔,表明你曾经有过一次错误提交,因而当你一旦提交该题“AC”后,就要与你算一算帐了,总共该题错误提交了几回。虽然你在题数上,大步地跃上了一个台阶,但是在耗时上要摊上你共花去的时间。特别是,曾经有过的错误提交,每次都要摊上一定的单位时间分。这样一来,你在做出的题数上,可能领先别人很多,但是,在做出同样题数的人群中,你可能会在耗时上处于排名的劣势。
例如:某次考试一共8题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数,但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上一对括号,里面有个整数b,那就表示该学生提交该题AC了,耗去了时间a,同时,曾经错误提交了b次,因此对于下述输入数据:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#define    MAX 1000

typedef struct
{
    char    name[11];
    int    sum;
    int    total;
}credit;

int cmp(const void *a, const void *b)
{
    if ((*(credit *)a).total != (*(credit *)b).total)
        return (*(credit *)a).total - (*(credit *)b).total;
    else if ((*(credit *)b).sum != (*(credit *)a).sum)
        return (*(credit *)b).sum - (*(credit *)a).sum;
    else
        return strcmp((*(credit *)b).name, (*(credit *)a).name);
}

int main(void)
{
    int    res, t, f;
    int    i, n, m, j;
    char    style[10];
    credit    c[MAX] = {0};

    scanf("%d%d", &n, &m);
    for (i = 0; scanf("%s", c[i].name) != EOF; i++)
    {
        for (j = 0; j < n; j++)
        {
            scanf("%s", style);
            res = sscanf(style, "%d(%d)", &t, &f);
            if (res == 2)
            {
                c[i].total++;
                c[i].sum += t + f * m;
            }
            else if (res == 1 && t > 0)
            {
                c[i].total++;
                c[i].sum += t;
            }
        }
    }

    qsort(c, i, sizeof(credit), cmp);
    for (i--; i >= 0; i--)
        printf("%-10s %2d %4d\n", c[i].name, c[i].total, c[i].sum);

    return 0;
  }

2092 整数解

有二个整数,它们加起来等于某个整数,乘起来又等于另一个整数,它们到底是真还是假,也就是这种整数到底存不存在,实在有点吃不准,你能快速回答吗?看来只能通过编程。
∵x + y = n
∴y = n - x
∵xy = m
∴(n - x) * x = m
∴x2 - nx + m = 0
∵m是整数,且xy = m
∴x、y都是整数。
∴要判断是否有整数解,就要判断方程:x2 - nx + m = 0的△是否为完全平方数。

#include <math.h>
#include <stdio.h>
#define s(x)   ((x)*(x))
int main(void)
{
    int x, y;

    while (scanf("%d%d", &x, &y), x+y)
        puts(s(x)-4*y >= 0 && s(x)-4*y - s((int)sqrt(s(x)-4*y)) == 0 ? "Yes" : "No");
    return 0;
}
		
		#include<iostream>

法二

using namespace std;
#include<cmath>
//#include<string>
int main()
{
	int n, m;
	while (cin>>n>>m)
	{
		if (n == 0 && m == 0)
		{
			break;
		}
		int delta = n*n - 4 * m;
		if (delta < 0)
		{
			cout << "No" << endl;
			continue;
		}
		int ac = sqrt(delta);
		if (ac*ac != delta)
		{
			cout << "No" << endl;
			continue;
		}
		int frac_1 = n + ac;
		int frac_2 = n - ac;
		if (frac_1 % 2 == 0 && frac_2 % 2 == 0)
		{
			cout << "Yes" << endl;
		}
		else
		{
			cout << "No" << endl;
		}
	}
	
	return 0;
}

2091 空心三角形

#include <iostream>
using namespace std;
int main()
{
    int n, flag=0;
    char c;
    while(cin>>c&&c!='@'){
        cin>>n;
        if(flag!=0) cout<<endl;
        for(int i=1; i<=n; i++){ //共有n行
         if(i!=n){
	        //当不是第n行的时候
			for(int j=1;j<=n+i-1;j++){
  				 if(j==(n-i+1)||j==(n+i-1)){
  				  cout << c;   //在指定的位置输出字符
  				  }
  				  else
  				  cout<<" ";   //非指定的位置输出的是空格
  			  }
  	else{ //当是最后一行的时候输出的是 2*n-1个指定符号
	for(int j=1;j<=2*n-1;j++){
	cout<<" ";
	}
	flag=1; //换行标志
	}
}
return 0;
}

2090 算菜价

妈妈每天都要出去买菜,但是回来后,兜里的钱也懒得数一数,到底花了多少钱真是一笔糊涂帐。现在好了,作为好儿子(女儿)的你可以给她用程序算一下了,呵呵。

#include <stdio.h>

int main(void)
{
    double sum = 0, d, n;

    while (scanf("%*s") != EOF)
    {
        scanf("%lf%lf", &n, &d);
        sum += n * d;
    }
    printf("%.1f\n", sum);

    return 0;
}

2089 不要62

不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914

  • 这里的方法是暴力穷举的方法

      #include <stdio.h>		
      int A(int n)
      {
              if (n % 10 == 4 || n % 100 == 62)//先求余再整除 这里就是有4或者是62连着一起出现了
           {   
              return 0;
              n /= 10;
          }
          return 1; //如果没有符合条件的那就是一个好的车牌号 
      }	
      int main(void)
      {
          int i,a,b;
          int *a = new int[1000000]; //申请一个数组
          a[0] = 0; //对这个数组初始化
          scanf("%d %d",&a,&b);
          for (i = 1; i < 1000000; i ++)
          {
           a[i]=a[i-1]+A(i); 进行累加
      		while(~scanf("%d%d",&n,&m))
      		{
      			if(n==0&&m==0)
      			break;
      			printf("%d\n",a[m]-a[n-1]);
      		}
      		return 0;
          }
    

    2088 Box of Bricks

    就是一堆砖使它们一样高最少移动多少次

      #include <stdio.h>
      int main(void)
      {
          int n, i, s, t, c = 0;
          int a[50];
          while (scanf("%d", &n), n) //几个数
          {
              if (c++) putchar('\n');
              for (s = i = 0; i < n; i++)
              {
                  scanf("%d", a + i);
                  s += a[i];  //总砖数
              }
              s /= n;//平均一堆几个
              for (t = i = 0; i < n; i++)  //用t记录要移动的个数 就是大于平均值的那一部分要记上
              {
                  if (a[i] > s)
                      t += a[i] - s;
              }
              printf("%d\n", t);        
          }
      
          return 0;
      	}
    

2087 剪花布条 (字符串处理)

  • 输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行

  • char *strstr( const char *str1, const char *str2 );
    功能:函数返回一个指针,它指向字符串str2 首次出现于字符串str1中的位置,如果没有找到,返回NULL。

      #include <stdio.h>
      #include <string.h>
      int main(void)
      {
          int len, c; 
          char *p;
          char a[1001], b[1001]; //a是大布头b是小布头
          while (scanf("%s", a), a[0] != '#')//以#结束
          {
              scanf("%s", b);
              len = strlen(b); //长度
              for (c = 0, p = a; p = strstr(p, b); c++,p += len);
              printf("%d\n", c);
          }
      
          return 0;
      }
    

2086 A1 = ?

有如下方程:Ai = (Ai-1 + Ai+1)/2 - Ci (i = 1, 2, 3, … n).
若给出A0, An+1, 和 C1, C2, …Cn.
请编程计算A1 = ?
Ai = (Ai-1 + Ai+1)/2 - Ci (i = 1, 2, 3, … n). 用A5做示范,就能猜测出公式来。证明方法可以采用数学归纳法。这里证明从略。
A5 = (A4 + A6) / 2 - C5
A4 = (A3 + A5) / 2 - C4 = A3 / 2 + A4 / 4 + A6 / 4 - C5 / 2 - C4
=>A4 = 2A3/3 + A6/3 - 2C5/3 - 4C4/3
A3 = (A2 + A4) / 2 - C3 = A2 / 2 + A3 / 3 + A6 / 6 - C5 / 3 - 2C4 / 3 - C3
=>A3 = 3A2/4 + A6/4 - C5/2 - C4 - 3C3/2
A2 = (A1 + A3) / 2 - C2 = A1 / 2 + 3A2 / 8 + A6 / 8 - C5 / 4 - C4 / 2 - 3C3 / 4 - C2
=>A2 = 4A1/5 + A6/5 - 2C5/5 - 4C4/5 - 6C3/5 - 8C2/5
A1 = (A0 + A2) / 2 - C1 = A0 / 2 + 2A1 / 5 + A6 / 10 - C5 / 5 - 2C4 / 5 - 3C3 / 5 - 4C2 / 5 - C1
=>A1 = 5A0/6 + A6/6 - C5/3 - 2C4/3 - C3 - 4C2/3 - 5C1/3
算到这里,我想你已经总结出公式了:
A1 = (n * A0 + An+1 - 2 * Cn - 4 * Cn-1 - … - 2 * i * Cn-i+1 - 2 * n * C1) / (n + 1)

#include <stdio.h>

int main(void)
{
    int n, i;
    double a0, an1, a1;
    double c[3000];

    while (scanf("%d", &n) != EOF)
    {
        scanf("%lf%lf", &a0, &an1);
        for (i = 0; i < n; i++)
            scanf("%lf", c + i);
        a1 = n * a0 + an1;
        for (i = 1; i <= n; i++)
            a1 -= 2 * i * c[n - i];
        printf("%.2f\n", a1 / (n + 1));
    }

    return 0;
}

2085 核反应堆

高能质点碰击核子时,质点被吸收,放出3个高能质点和1个低能质点;
低能质点碰击核子时,质点被吸收,放出2个高能质点和1个低能质点。
假定开始的时候(0微秒)只有一个高能质点射入核反应堆,每一微秒引起一个事件发生(对于一个事件,当前存在的所有质点都会撞击核子),试确定n微秒时高能质点和低能质点的数目。
输入含有一些整数n(0≤n≤33),以微秒为单位,若n为-1表示处理结束
公式:
g[i] = 3 * g[i - 1] + 2 * d[i - 1];
d[i] = g[i - 1] + d[i - 1];

#include <stdio.h>
int main(void)
{
    int n, i;
    __int64 g[34] = {1}; //初始化
    __int64 d[34] = {0};	
    for (i = 1; i < 34; i++)
    {
        g[i] = 3 * g[i - 1] + 2 * d[i - 1];
        d[i] = g[i - 1] + d[i - 1];
    }	
    while (scanf("%d", &n), n != -1)
        printf("%I64d, %I64d\n", g[n], d[n]);	
    return 0;
}

2084 数塔

在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的:有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
已经告诉你了,这是个DP的题目,你能AC吗?

  • input:输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。

  • 动态规划问题
    状态转移方程
    array[i][j]+=MAX{array[i-1][j-1],array[i-1][j]}

      #include <iostream>   
      using namespace std;    
      int main()
      {	
      	int array[101][101];
      	int i,j;
      	int C,N,Max;
      	for(i=0;i<=100;i++)
      	{
      		for(j=0;j<=100;j++)
      			array[i][j]=0;
      	}
      	cin>>C;
      	while(C--)
      	{
      		cin>>N;
      		for(i=1;i<=N;i++)
      		{
      			for(j=1;j<=i;j++)
      				cin>>array[i][j];
      		}
      		for(i=1;i<=N;i++)
      		{
      			for(j=1;j<=i;j++)
      			{
      				if(array[i-1][j-1]>=array[i-1][j])
      					array[i][j]+=array[i-1][j-1];
      				else
      					array[i][j]+=array[i-1][j];
      			}
      		}
      		Max=0;
      		for(i=1;i<=N;i++)
      			if(array[N][i]>Max)
      				Max=array[N][i];
      		cout<<Max<<endl;
      	}
      	return 0;
      }
    

2083 简易版之最短距离

寒假的时候,ACBOY要去拜访很多朋友,恰巧他所有朋友的家都处在坐标平面的X轴上。ACBOY可以任意选择一个朋友的家开始访问,但是每次访问后他都必须回到出发点,然后才能去访问下一个朋友。

  • 用暴力列举的方法

      #include<iostream>
      #include<algorithm>
      #include<cstring>
      #include<cmath>
      using namespace std;
      int main()
      {
      	int m, n;
      	int friends[505], mini[505];
      	cin >> m;
      	while (m--)
      	{
      		cin >> n;
      		memset(mini, 0, sizeof(mini));//初始化
      		for (int i = 0; i < n; i++)
      			cin >> friends[i]; //输入n个朋友的距离
      		for (int i = 0; i < n; i++)
      		{
      			for (int j = 0; j < n; j++)
      			{
      				mini[i] += abs(friends[j] - friends[i]); //绝对值 注意数学符号
      			}
      		}
      		sort(mini, mini + n);
      		cout << mini[0] << endl;
      	}
      	return 0;
      }
    

2082 找单词(母函数 不懂)

假设有x1个字母A, x2个字母B,… x26个字母Z,同时假设字母A的价值为1,字母B的价值为2,… 字母Z的价值为26。那么,对于给定的字母,可以找到多少价值<=50的单词呢?单词的价值就是组成一个单词的所有字母的价值之和,比如,单词ACM的价值是1+3+14=18,单词HDU的价值是8+4+21=33。(组成的单词与排列顺序无关,比如ACM与CMA认为是同一个单词)。

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		int value[30]={0},num[30]={0},dp[55][55]={{0}}; //初始化
		for(int i=1;i<=26;i++)
		{
			value[i]=i;
			cin>>num[i]; //输入每一组的值
		}
		dp[0][0]=1;//相加
		for(int i=1;i<=26;i++)
			for(int j=0;j<=50;j++)
				for(int k=0;k<=num[i]&&k*value[i]<=j;k++)
					dp[i][j]+=dp[i-1][j-k*value[i]];
		int result=0;
		for(int i=1;i<=50;i++)
			result+=dp[26][i];
		cout<<result<<endl;
	}
	return 0;
}

2081 手机短号

如果给你一个11位长的手机号码,你能找出对应的短号吗?2 13512345678 13787654321
得出 645678 654321

#include <stdio.h>
int main(void)
{
    int i, n;
    char c;
    scanf("%d%*c", &n);
    while (n--)
    {
        putchar('6');
        for (i = 0; i < 12; i++)
        {
            if ((c = getchar()) && i > 5)
                putchar(c);
        }
    }
    return 0;
}  

//按照字符来处理

2080 夹角有多大II

  • 输入两点的坐标 求它们的角度

  • 这里在C语言中acos()是弧度制的意思 弧度=(角度/180) PI -->角度=(弧度180)/PI

      #include <stdio.h>
      #include <math.h>
      const double pi = 3.1415926;
      int main()
      {
          int n;
          scanf("%d",&n);
          while(n--)
          {
              double x1,x2,y1,y2,t,a,b,c,max;
              scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
              a = sqrt(x1*x1+y1*y1);
              b = sqrt(x2*x2+y2*y2);
              c = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
              t = (a*a+b*b-c*c)/(2.0*b*a);
              t = acos(t)*180/pi;
              while(t>180)
              t-=180;
              printf("%.2lf\n",t);
          }
       
          return 0;
      }
    

2079 选课时间(题目已修改,注意读题)

  • 又到了选课的时间了,xhd看着选课表发呆,为了想让下一学期好过点,他想知道学n个学分共有多少组合。你来帮帮他吧。(xhd认为一样学分的课没区别)

      #include<cstring>
      #include<cstdio>
      int main()
      {
          int T,n,i,j,k,a,b,e[1010],c1[1010],c2[1010];   
          scanf("%d",&T);
          while(T--)
          {
              memset(e,0,sizeof(e));
              scanf("%d %d",&n,&k);     //要修n个学分 
              for(i=0; i<k; i++)
              {
                  scanf("%d %d",&a,&b);
                   e[a]=b;              //学分为a的有b门 
              }
              memset(c1,0,sizeof(c1));
              memset(c2,0,sizeof(c2));
              
              for(i=0; i<=e[1]; i++)   //将学分为1的初始化 
              c1[i]=1;
              
               for(i=2; i<=40; i++)
               {  
                      for(j=0; j<=40; j++)
                      {
                          for(k=0; k<=e[i]&&k*i+j<=40; k++)   //学分为i的e[i]门,控制个数 
                          {   
                              c2[k*i+j]+=c1[j];                 
                          }
                      }
                  for(j=0; j<=40; j++)
                  {
                      c1[j]=c2[j];
                      c2[j]=0;
                  }
              }
              printf("%d\n",c1[n]);
          }
          return 0;
      }
    

    2078 复习时间

  • 为了能过个好年,xhd开始复习了,于是每天晚上背着书往教室跑。xhd复习有个习惯,在复习完一门课后,他总是挑一门更简单的课进行复习,而他复习这门课的效率为两门课的难度差的平方,而复习第一门课的效率为100和这门课的难度差的平方。xhd这学期选了n门课,但是一晚上他最多只能复习m门课,请问他一晚上复习的最高效率值是多少?

  • 按题目的介绍,如果前一门复习的课程的难度为m,后一门为n。那他复习后一门的效率就为(m-n)*(m-n);
    自然,这里的m越大,n越小,它的效率自然就越高!
    而m最大值为初始状态100,因此,我们的任务就是求它这么多要复习的课程中,难度最小的一门。即最小的n。

  • 最高效率也就是 哪一门的效率最高 不要想复杂了

      #include <stdio.h>
      int main(void)
      {
          int t, n, c, m, i;	
          scanf("%d", &t);//几组数据
          while (t-- && scanf("%d%*d", &n))
          {
              for (m = 100, i = 0; i < n; i++)
              {
                  scanf("%d", &c);
                  if (c < m) m = c;
              }
              printf("%d\n", (100-m)*(100-m));
          }
          return 0;
      }
    

    2077 汉诺塔IV

    还记得汉诺塔III吗?他的规则是这样的:不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到小盘的上面。xhd在想如果我们允许最大的盘子放到最上面会怎么样呢?(只允许最大的放在最上面)当然最后需要的结果是盘子从小到大排在最右边。
    - 以为把n个盘按汉诺塔从1搬到3需要3n - 1(推导见2064)。搬n个盘需要m(n) = 2 * f(n-1) + 2 = 3n-1 + 1

      	#include <math.h>
      	#include <stdio.h>	
      	int main(void)
      	{
      	    int n, t;
      	    scanf("%d", &t);
      	    while (t-- && scanf("%d", &n))
      	        printf("%.0f\n", pow(3, n-1) + 1);	    
      	    return 0;
      	}	
    

2076 夹角有多大(题目已修改,注意读题)

时间过的好快,一个学期就这么的过去了,xhd在傻傻的看着表,出于对数据的渴望,突然他想知道这个表的时针和分针的夹角是多少。现在xhd知道的只有时间,请你帮他算出这个夹角。
注:夹角的范围[0,180],时针和分针的转动是连续而不是离散的。输入数据的第一行是一个数据T,表示有T组数据。每组数据有三个整数h(0 <= h < 24),m(0 <= m < 60),s(0 <= s < 60)分别表示时、分、秒。

  • 所有在h:m:s时,时针的角度为30h + m/2 + s/120;分针的角度为:6m + s/10;

      #include <stdio.h>
      int main(void)
      {
          int n;
          double h, m, s;
      
          scanf("%d", &n);
          while (n-- && scanf("%lf%lf%lf", &h, &m, &s))
          {
              if (h > 12) h -= 12;
              printf("%d\n", (h=fabs(30*h-11*m/2-11*s/120))>180?(int)(360-h):(int)h);
          }
          return 0;
      }
    

2075 A|B?

正整数A是否能被正整数B整除

#include<stdio.h>
int main(void)
{
	int n, a, b;	
	scanf("%d", &n);
	while(n-- && scanf("%d%d", &a, &b))
		puts(a % b ? "NO" : "YES");

	return 0;
}

2074 叠筐

AAAAAAAAA
ABBBBBBBBBA
ABAAAAAAABA
ABABBBBBABA
ABABAAABABA
ABABABABABA
ABABAAABABA
ABABBBBBABA
ABAAAAAAABA
ABBBBBBBBBA
AAAAAAAAA

#include <stdio.h>
#include <stdlib.h>
int main()
{
    //外框尺寸
    int n;
    int i;
    int j;
    int k;
    //中心花色字符和外框花色字符
    char ch1,ch2;
    char t;
    //用于判断在打印图样时需不需要先换行
    int flag=0;
    while(~scanf("%d",&n))
    {
        //若非第一个打印的图案则先换行
        if(flag)
            printf("\n");
        flag++;
        //防止读入回车符
        getchar();
        //开一个大小为n的字符数组
        char *p=(char *)malloc(sizeof(char)*n);
        scanf("%c %c",&ch1,&ch2);
        //如果外框尺寸为1则直接打印中心图案
        if(n==1)
        {
            printf("%c\n",ch1);
            continue;
        }
        //对外框尺寸n进行分情况讨论
        if(n/2%2==0)
        {
            t=ch1;
            ch1=ch2;
            ch2=t;
        }
        //让ch2充满整个数组
        for(i=0;i<n;i++)
        {
            p[i]=ch2;
        }
        //打印上半截图案
        for(i=0;i<=n/2;i++)
        {
            //若输出的是第一行则把首元素和尾元素置为空格
            if(i==0)
            {
                p[0]=' ';
                p[n-1]=' ';
                for(k=0;k<n;k++)
                    printf("%c",p[k]);
                printf("\n");
                p[0]=ch2;
                p[n-1]=ch2;
            }
            //下标为级数的行
            else if(i%2==1)
            {
                for(j=i;j<n-i;j++)
                    p[j]=ch1;
                for(k=0;k<n;k++)
                    printf("%c",p[k]);
                printf("\n");
            }
            //下标为偶数的行
            else
            {
                for(j=i;j<n-i;j++)
                    p[j]=ch2;
                for(k=0;k<n;k++)
                    printf("%c",p[k]);
                printf("\n");
            }
        }
        //打印下半截图案
        for(i=n/2+1;i<n;i++)
        {
            //若输出的是最后一行则把首元素和尾元素置为空格
            if(i==n-1)
            {
                p[0]=' ';
                p[n-1]=' ';
                for(j=1;j<n-1;j++)
                    p[j]=ch2;
                for(k=0;k<n;k++)
                    printf("%c",p[k]);
                printf("\n");
            }
            //下标为奇数的行
            else if(i%2==1)
            {
                for(j=i;j>=n-i;j--)
                    p[j]=ch1;
                for(k=0;k<n;k++)
                    printf("%c",p[k]);
                printf("\n");
            }
            //下标为偶数的行
            else
            {
                for(j=i;j>=n-i;j--)
                    p[j]=ch2;
                for(k=0;k<n;k++)
                    printf("%c",p[k]);
                printf("\n");
            }
        }
        free(p);
    }
    return 0;
}

2073 无限的路

在这里插入图片描述

  • t通过求距离再调用的方法

      #include<stdio.h>
      #include<math.h>
      double distance(int x,int y)
      {
          double sum=0;
          int i,j;
          double t=sqrt((double)2);//根2
          for(i=1;i<x+y;i++)
          {
              sum+=i*t; //斜率为-1的路
          }
          sum+=t*x;最后一段路
          for(j=0;j<x+y;j++)
          {
              sum+=sqrt(double(j*j+(j+1)*(j+1)));//斜率不是-1的路
          }
          return sum;
      }
      int main()
      {
          int times,x1,y1,x2,y2;
          scanf("%d",×);
          while(times--)
          {
              scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
              printf("%.3lf\n",fabs(distance(x2,y2)-distance(x1,y1)));
          }
      }
    

2072 单词数

you are my friend
/#
4

using namespace std;
int main(void)
{
    set <string> st;
    string s = "";
    char c;	
    while ((c = getchar()) != '#')
    {
        s += c;
        while (c != '\n')
        {
            while ((c = getchar()) != ' ' && c != '\n')
                s += c;
            if (s.length()) st.insert(s);
            s = "";
        }
        cout << st.size() << endl;
        st.clear();
    }
    return 0;
}

2071 Max Num

There are some students in a class, Can you help teacher find the highest student

#include <stdio.h>
int main(void)
{
    int t, n;
    double c, b;
    scanf("%d", &t);
    while (t-- && scanf("%d", &n))
    {
        c = 0;
        while (n-- && scanf("%lf", &b))
            if (c < b) c = b;
        printf("%.2f\n", c);
    }
    return 0;
}

2070 Fibbonacci Number

Your objective for this question is to develop a program which will generate a fibbonacci number. The fibbonacci function is defined as such:

#include <stdio.h>
int main(void)
{
	int i;
	__int64 f[51]={0, 1};
	for(i = 2; i < 51; i++)
		f[i] = f[i-1] + f[i-2];
	while(scanf("%d", &i), i + 1)
		printf("%I64d\n", f[i]);
	return 0;
}

2069 Coin Change

Suppose there are 5 types of coins: 50-cent, 25-cent, 10-cent, 5-cent, and 1-cent. We want to make changes with these coins for a given amount of money.how many times?

#include<bits/stdc++.h>
using namespace std;
const int coin[]={1,5,10,25,50};
int dp[255][105];      //dp[j][k]:用k个硬币组成j元的个数
int main(){
    int n;
    while(cin>>n){
        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for(int i=0;i<5;i++){
            for(int k=1;k<=100;k++){      //k个硬币
                    for(int j=coin[i];j<=n;j++) {
                        dp[j][k]+=dp[j-coin[i]][k-1];
                }
            }
        }
        int res=0;
        for(int i=0;i<=100;i++)
            res+=dp[n][i];
        cout<<res<<endl;
    }
    return 0;
}

法2 暴力求解

#include <stdio.h>
int main(void)
{
    int n, d[251] = {0};
    int c1, c5, c10, c25, c50;
    for (n = 0; n < 251; n++)
    for (c50 = 0; c50 * 50 <= n; c50++)
    for (c25 = 0; c50 * 50 + c25 * 25 <= n; c25++)
    for (c10 = 0; c50 * 50 + c25 * 25 + c10 * 10 <= n; c10++)
    for (c5 = 0; c50 * 50 + c25 * 25 + c10 * 10 + c5 * 5 <= n; c5++)
    {
        c1 = n - (c50 * 50 + c25 * 25 + c10 * 10 + c5 * 5);
        if (c1 + c5 + c10 + c25 + c50 <= 100) d[n]++;
    }
    while (scanf("%d", &n) != EOF)
        printf("%d\n", d[n]);
    return 0;
}

2068 RPG的错排

  • 本题中"女生们只要求他答对一半或以上就算过关",因此就应该错排0个,1个,2个一直到n/2个,然后与排列数相乘再累加即可。注意这里应该选择的是组合数公式,而不是排列数公式

     #include<cstdio>
     #include<iostream>
     #include<sstream>
     #include<cstdlib>
     #include<cstring>
     #include<string>
     #include<climits>
     #include<cmath>
     #include<algorithm>
     #include<queue>
     #include<vector>
     #include<stack>
     #include<set>
     #include<map>
     using namespace std;
     __int64 C_n_m(int n,int m)
     {
         __int64 i,up,down;//分子,分母
         up=down=1;
         for(i=n;i>=n-m+1;i--)
             up*=i;
         for(i=m;i>=1;i--)
             down*=i;
         return up/down;
     }
     int main()
     {
         int n;
         int i;
         __int64 f[30];
         f[0]=0;
         f[1]=0;
         f[2]=1;
         __int64 sum;
         for(i=3; i<=25; i++)
             f[i]=(i-1)*(f[i-1]+f[i-2]);
         while(~scanf("%d",&n))
         {
             sum=0;
             if(n==0)
                 break;
             else
             {
                 for(i=0; i<=n/2; i++)
                     sum+=f[i]*C_n_m(n,i);
             }
             printf("%lld\n",sum+1);//当全部答对时f[0]=1,因此要加1.
         }
     }
    

2067 小兔的棋盘

小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望。不过没过几天发现了棋盘的好玩之处。从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n),现在小兔又想如果不穿越对角线(但可接触对角线上的格点),这样的路径数有多少?小兔想了很长时间都没想出来,现在想请你帮助小兔解决这个问题,对于你来说应该不难吧!

#include <cstdio>
int main()
{
	__int64 Catalan[40] = {0};
	Catalan[0] = 1;
	Catalan[1] = 1;
	for (int i = 2 ; i <= 35 ; i++)
		for (int j = 0 ; j <= i - 1 ; j++)
			Catalan[i] += Catalan[j] * Catalan[i - 1 - j];
	int num = 1;
	int n;
	while (~scanf ("%d",&n) && n != -1)
		printf ("%d %d %I64d\n",num++,n,Catalan[n] * 2);
	return 0;
}

2066 一个人的旅行

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

const int INF = 1 << 20;  // INF 的设置一定要足够的大
const int maxn = 1000 + 5;
int dist[maxn], map[maxn][maxn], vis[maxn];
int T, S, D, n;
void Init()
{
    for (int i = 0; i < maxn; i++)  // 只能小于,不能等于,否则会TLE!!
    {
        for (int j = 0; j < maxn; j++)  // 只能小于,不能等于, 否则会TLE!!
            map[i][j] = (i == j ? 0 : INF);
    }
    int st, end, time;
    n = 0;
    for (int i = 0; i < T; i++)
    {
        scanf("%d%d%d", &st, &end, &time);
        if (map[st][end] > time)  // 有重边
            map[st][end] = map[end][st] = time;
        // 找出最大边的编号
        n = max(n, max(st, end));
    }
    n++;   // 假设是理想中的终点(比最大的顶点大1)的编号
    for (int i = 0; i < S; i++)
    {
        scanf("%d", &st);
        map[0][st] = map[st][0] = 0; // 草儿家到相邻城市的距离为0
    }
    for (int i = 0; i < D; i++)
    {
        scanf("%d", &st);
        map[st][n] = map[n][st] = 0;  // 想去的地方到理想中的终点距离为0
    }
}	
void Dijkstra()
{
    for (int i = 0; i <= n; i++)  // 从0改为1
        dist[i] = map[0][i];  // 以草儿家和她相邻的点作为起点,求出该起点到相邻点的时间
    memset(vis, 0, sizeof(vis));
    for (int i = 0; i <= n; i++)    // 0 改为 1 也行
    {
        int u;
        int maxx = INF;
        for (int j = 0; j <= n; j++)  
        {
            if (!vis[j] && dist[j] < maxx)
                maxx = dist[u=j];
        }
        vis[u] = 1;
        for (int j = 0; j <= n; j++)
        {
            if (dist[j] > dist[u] + map[u][j])
                 dist[j] = dist[u] + map[u][j];
        }
    }
}	
int main()
{
    while (scanf("%d%d%d", &T, &S, &D) != EOF)
    {
        Init();
        Dijkstra();
        printf("%d\n", dist[n]);
    }
    return 0;
}
--------------

2065 "红色病毒"问题

Problem Description
医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色病毒",经研究发现,该病毒及其变种的DNA的一条单链中,胞嘧啶,腺嘧啶均是成对出现的。
现在有一长度为N的字符串,满足一下条件:
(1) 字符串仅由A,B,C,D四个字母组成;
(2) A出现偶数次(也可以不出现);
(3) C出现偶数次(也可以不出现);
计算满足条件的字符串个数.
当N=2时,所有满足条件的字符串有如下6个:BB,BD,DB,DD,AA,CC.
由于这个数据肯能非常庞大,你只要给出最后两位数字即可.
如何找到规律
n=1 --〉B,D ans= 2=12=20*2=20(2^0+1)
n=2 --> ans=6; =2
3=21*3=21(2^1+1)
n=3 --> ans=20 =45=22*5=22(2^2+1)
n=4 —> ans=72 = 8
9=239=23(23+1)
n=k ----> ??? =2k-1*(2k-1+1)
于是题目转化为快速幂问题…

#include<stdio.h>
int main()
{
    int t,cnt,ans,i;
    _int64 n;
    while(scanf("%d",&t)!=EOF,t)
    {
     for(i=1;i<=t;i++)
     {
        cnt=2;
        ans=1;
        scanf("%I64d",&n);
        n--;
        while(n)
        {
            if(n&1)   
            {
                ans*=cnt;
                ans%=100;
                n--;
            }
            else
            {
                cnt*=cnt;
                cnt%=100;
                n>>=1;
            }
        }
     printf("Case %d: %d\n",i,(ans*(ans+1))%100);
     }
     putchar(10);
    }
    return 0;
}

2064 汉诺塔III

我们设f(n)为把n个盘从1移到3所需要的步数,当然也等于从3移到1的步数。
看什么的图就知道,要想把第n个盘从1移到3,需要想把前n-1个从1移动3,再从3->1最后再1->3。
而第n个盘要从1->2->3经历2步。
∴f(n) = 3 × f(n-1) + 2;
f(1) = 2;
f(n) = 3 × f(n-1) + 2
f(1) = 2
=>
f(n) + 1 = 3 × [f(n-1) + 1]
f(1) + 1 = 2 + 1 = 3
=>
f(n) + 1 = 3n
=>
f(n) = 3n - 1

#include <math.h>
#include <stdio.h>
int main(void)
{
	int n;
	while (scanf("%d", &n) != EOF)
	printf("%.0f\n", pow(3, n) - 1);
	return 0;
}

**2063 过山车

RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?

  • 这就是匈牙利算法的流程,其中找妹子是个递归的过程,最最关键的字就是“腾”字
    其原则大概是:有机会上,没机会创造机会也要上

     bool find(int x){
     	int i,j;
     	for (j=1;j<=m;j++){    //扫描每个妹子
     		if (line[x][j]==true && used[j]==false)      
     		//如果有暧昧并且还没有标记过(这里标记的意思是这次查找曾试图改变过该妹子的归属问题,但是没有成功,所以就不用瞎费工夫了)
     		{
     			used[j]=1;
     			if (girl[j]==0 || find(girl[j])) { 
     				//名花无主或者能腾出个位置来,这里使用递归
     				girl[j]=x;
     				return true;
     			}
     		}
     	}
     	return false;
     }
    

	#include<stdio.h>
	#include<string.h>
	int line[510][510],boy[510],used[510];
	int n,m;
	int Find(int x)
	{
	    int i,j;
	    for(i=1;i<=m;i++)//遍历所有被选者 
	    {
	       if(line[x][i]==1&&used[i]==0)
	       {//如果 x对i有好感且在这一个递归选取阶段没有被选取(哪怕是暂时选取,新的递归可能会换) 
	          used[i]=1;//标记被选取 
	          if(boy[i]==0||Find(boy[i]))//如果被选者没有归属或他的归属着可以调换(他的归属者可以选择其它被选者) 
	          {
	             boy[i]=x;//将归属定为 x 
	             return 1;
	          }
	       }
	    }
	    return 0;
	}
	int main()
	{
	    int i,j,k,x,y,sum;
	    while(scanf("%d %d %d",&k,&n,&m),k!=0)
	    {
	       memset(line,0,sizeof(line));
	       memset(boy,0,sizeof(boy));
	       memset(used,0,sizeof(used));
	       for(i=0;i<k;i++)
	       {
	          scanf("%d %d",&x,&y);
	          line[x][y]=1;//表示 x希望与 y有关系 
	       } 
	       sum=0;//记录能撮合的情侣对数 
	       for(i=1;i<=n;i++)  
	       {
	           memset(used,0,sizeof(used));//每次都要清 0 
	           if(Find(i)) sum++;//找到一对就记录 
	       }
	       printf("%d\n",sum);
	    }
	    return 0;
	}

2062 Subset sequence

考虑一个集合 An = { 1, 2, …, n}。比如,A1={1},A3={1,2,3}。我们称一个非空子集元素的排列为一个子集序列。对所有的子序列按字典顺序排序。你的任务就是给出第m个子序列。

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int i,n;//元素个数; 
	int t;//所求子集位于分组后的第几组; 
	int s[25];//后面将子集按字典序分组后每组的初始首元素; 
	__int64 m;//位于第几个子集; 
	__int64 c[25]={0};//c[i]表示n=i时的分组每组中子集数; 
	for(i=0;i<25;i++)
	{
		c[i]=c[i-1]*(i-1)+1;//c[n]=(n-1)*c[n-1]+1; 
	}
	while(scanf("%d%I64d",&n,&m)!=EOF)
	{
		for(i=0;i<25;i++)
		{
			s[i]=i;//每循环一次就重新归位每组首元素; 
		}
		while(n>0&&m>0)
		{
			t=m/c[n]+1;
			if(m%c[n]==0)
			t--;
			if(t>0)//得到第m个子集在分组后的第t组 
			{
				printf("%d",s[t]);
				for(i=t;i<=n;i++)
				{
					s[i]=s[i+1];//在第n组中,第2个元素在第n个时变为它的下一个数 
				}
				m=m-((t-1)*c[n]+1);//m变为表示在剩余子集中位于第几个 
				printf(m==0?"\n":" ");
			}
			n--;//n依次递减,直到执行上面的if代码或退出 
		}
	}
	return 0;
} 

2061 Treasure the new start, freshmen!

GPA = (C1 * S1 + C2 * S2 +……+Ci * Si……) / (C1 + C2 + ……+ Ci……) (1 <= i <= K, Ci != 0)
如果有一门课程成绩在0到60之间,则GPA将不存在。
简单数值计算

#include <stdio.h>

int main(void)
{
    int i, t, n;
    double s[2], c[2];
    scanf("%d", &t);
    while (t-- && scanf("%d", &n))
    {
        for (s[1]=c[1]=i=0; n--; )
        {
            scanf("%*s%lf%lf", c, s);
            if (i) continue;
            if (s[0] < 60 && s[0] >= 0) i = 1;
            s[1] += s[0]*c[0];
            c[1] += c[0];
        }
        printf(i?"Sorry!\n":"%.2f\n", s[1]/c[1]);
        if (t) putchar('\n');
    }
    return 0;
}

2060 Snooker

题意为,给你场上剩下的球数m , 和 a ,b 两名队员目前得分,现在假设a将
所有的球m都打入洞中,然后让你输出是否最终a的得分会超过b;总共有15个红球,和6个有颜色的球,每个红球的得分为1 ,6个有颜色的球分别为2 , 3, 4 ,5, 6, 7 ;因为 要求最大得分,需要考虑的情况有两种;A :当 m > 6时 ,应该将有颜色的球都取了,有色球得分为2 + 3 + 4 + 5 + 6 + 7 ,有色球总得分为27 ;然后再取红球 m - 6 ,本来得分应该是 ( m - 6 ) * 1 ,但是由于有色球全部打进洞后,每个球需要额外增加黑球(最高得分)的得分;所以红球总得分为( m - 6 ) * 1 + ( m- 6 ) * 7 ;总得分为( m - 6 ) * 8 + 27 ;
B:当 m <= 6 时 ,应该由价值最高的黑球( 7 分) 向前依次增加求和,又因为有色球满足等差数列 ,由前6项减去前 6 - m项和,所以求得为( 7 - m + 1 + 7 ) * m / 2 ( 这里直接通过得分来计算的)。因此,第二种情况的得分为( 15 - m ) *m/ 2。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int main()
{
    int t,n,a,b;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&a,&b);
        if(n>6)
            a = a+(n-6)*8+27;
        else
            a = a+(15-n)*n/2;
        if(a>=b)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

2059 龟兔赛跑 (动态规划)

  • 动态规划

  • 状态转移方程: dp[i]=min(Min,dp[j]+time)
    本题目包含多组测试,请处理到文件结束。每个测试包括四行:
    第一行是一个整数L代表跑道的总长度
    第二行包含三个整数N,C,T,分别表示充电站的个数,电动车冲满电以后能行驶的距离以及每次充电所需要的时间
    第三行也是三个整数VR,VT1,VT2,分别表示兔子跑步的速度,乌龟开电动车的速度,乌龟脚蹬电动车的速度
    第四行包含了N(N<=100)个整数p1,p2…pn,分别表示各个充电站离跑道起点的距离,其中0<p1<p2<… 其中每个数都在32位整型范围之内。

      #include <stdio.h>
      #include <string.h>
      #include <algorithm>
      using namespace std;
       
      int main()
      {
          int t,n,a,b;
          scanf("%d",&t);
          while(t--)
          {
              scanf("%d%d%d",&n,&a,&b);
              if(n>6)
                  a = a+(n-6)*8+27;
              else
                  a = a+(15-n)*n/2;
              if(a>=b)
                  printf("Yes\n");
              else
                  printf("No\n");
          }
          return 0;
      }
    

2058 The sum problem

Given a sequence 1,2,3,…N, your job is to calculate all the possible sub-sequences that the sum of the sub-sequence is M.
我们都知道,在连续的整数序列里,1, 2, 3, …, n-1, n, n+1, …
∵2n = [(n-1) + (n+1)] = [(n-2) + (n+2)] = … = [1 + (2n-1)]
∴(n-m) + (n-m+1) + … + n-1 + n + n+1 + … + (n+m-1) + (n+m) = (2m+1) × n
∵2m+1是奇数
∴如果X能被2m+1整除(即能被分割成2m+1份),且n = X / (2m+1)
则X = (n-m) + (n-m+1) + … + n-1 + n + n+1 + … + (n+m-1) + (n+m)
同理,在整数序列中,又有这样的规律:
∵n + (n+1) = (n-1) + (n+2) = … = 1 + 2n
∴(n-m) + (n-m+1) + … + (n+m+1) = (m+1)(2n+1)
∴如果X能被(2n+1)整除,且X / (2m+2) = n
则X = (n-m) + (n-m+1) + … + (n+m+1)
运算的时候,保证n-m大于0,n+m+1或n+m小于给定的上界即可。

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
    int N,M,len,a;
    while(scanf("%d%d",&N,&M) && N&&M)
    {
        len = sqrt(2.0*M)+1;
        while(--len)
        {
            a = M/len - (len+1)/2;
            if((a+a+len+1)*len/2 == M)
            printf("[%d,%d]\n",a+1,a+len);
        }
        printf("\n");
    }
    return 0;
}

2057 A + B Again

  • 十六制 加法

      #include<iostream>
      #include<cstdio>
      using namespace std;
      int main(){
      		_int64 a,b,sum;
      		while(scanf("%I64X %I64X",&a,&b)!=EOF){
      			 sum=a+b;
      			if(sum<0){
      				sum=-sum;
      				printf("-");
      			}
      			printf("%I64X\n",sum);
      		}		
      }
    

2056 Rectangles

Problem Description Given two rectangles and the coordinates of two points on the diagonals of each rectangle,you have to calculate the area of the intersected part of two rectangles. its sides are parallel to OX and OY .

  • 给出两个矩形在对角线上的顶点的坐标,要求你计算两个矩形的公共部分的面积。
    数学计算。

     #include <cstdio>
     #include <algorithm>
     using namespace std;
     
     int main(void)
     {
         int i;
         double a[2], b[2];
         double x[4], y[4];
     
         while (scanf("%lf%lf", x, y) != EOF)
         {
             for (i = 1; i < 4; i++)
                 scanf("%lf%lf", x+i, y+i);
             if (x[0] > x[1]) swap(x[0], x[1]);
             if (y[0] > y[1]) swap(y[0], y[1]);
             if (x[2] > x[3]) swap(x[2], x[3]);
             if (y[2] > y[3]) swap(y[2], y[3]);
             a[0] = x[0] > x[2] ? x[0] : x[2];
             a[1] = x[1] < x[3] ? x[1] : x[3];
             b[0] = y[0] > y[2] ? y[0] : y[2];
             b[1] = y[1] < y[3] ? y[1] : y[3];
             printf("%.2f\n", a[0]<a[1] && b[0]<b[1]? (b[1]-b[0])*(a[1]-a[0]) : 0);
         }
     
         return 0;
     }
    

2055 An easy problem : jd

我们定义f(A) = 1, f(a) = -1, f(B) = -2, … f(Z) = -26;
给你一个字母x 以及一个数字y ,要求你输出 y + f(x)的值。

#include <stdio.h>
int main()
{
int n, a;
char c;
scanf("%d%*c", &n);
while (n-- && scanf("%c%d%*c", &c, &a))
printf("%d\n", a + (c < 97 ? c - ‘A’ + 1 : ‘a’ - c - 1));
return 0;
}

2054 A == B ?

给你两个数A和B,如果A等于B就输出"YES",否则输出"NO"。 字符处理 猜也能猜到,本题的数据不可能是简单到直接能保存进整型里。
它可能有10000位的长度,所以需要保存到字符串里。
比较的时候,需要注意的是:像0001.00与1是相同的。

#include <stdio.h>
#include <string.h>

void A(char *s)
{
    int len = strlen(s);
    char *p = s + len - 1;
    if (strchr(s, '.'))
    while (*p == '0') *p-- = 0;
    if (*p == '.') *p = 0;
}

int main(void)
{
    char *pa, *pb;
    char a[100024], b[100024];

    while (scanf("%s%s", &a, &b) != EOF)
    {
        pa = a; pb = b;
        while (*pa == '0') pa++;
        while (*pb == '0') pb++;
        A(pa); A(pb);
        puts(strcmp(pa, pb) ? "NO" : "YES");
    }

    return 0;
}

2053 Switch Game

There are many lamps in a line. All of them are off at first. A series of operations are carried out on these lamps. On the i-th operation, the lamps whose numbers are the multiple of i change the condition ( on to off and off to on ).

Consider the second test case:

The initial condition : 0 0 0 0 0 …
After the first operation : 1 1 1 1 1 …
After the second operation : 1 0 1 0 1 …
After the third operation : 1 0 0 0 1 …
After the fourth operation : 1 0 0 1 1 …
After the fifth operation : 1 0 0 1 0 …

#include <math.h>
#include <stdio.h>
#define S(x) (((int)x)*((int)x))
int main(void)
{
    int n;
    while (scanf("%d", &n) != EOF)
        printf("%d\n", S(sqrt(n)) == n);

    return 0;
}

2052 Picture

±–+
| |
| |
±–+

#include <stdio.h>
int main(void)
{
    int w, h, i, j;
    while (scanf("%d%d", &w, &h) != EOF)
    {        
        putchar('+');
        for (i = 0; i < w; i++)
            putchar('-');
        putchar('+');
        putchar('\n');
        for (j = 0; j < h; j++)
        {
            putchar('|');
            for (i = 0; i < w; i++)
                putchar(' ');
            putchar('|');
            putchar('\n');
        }
        putchar('+');
        for (i = 0; i < w; i++)
            putchar('-');
        printf("+\n\n");
    }
    return 0;
}

2051 Bitset (进制转化)

Give you a number on base ten,you should output it on base two.(0 < n < 1000)

#include<iostream>
#include<cstdio>
using namespace std;
int a[21];
int main(){
	int n;
	while(cin>>n){
		int i=0;
		while(n){
			a[i] = n%2;
			n /= 2;
			i++;
		}
		for(int j=i-1 ;j>=0 ;j--){
			cout<<a[j];
		}
		cout<<endl;
	}
	
	return 0;
}

2050 折线分割平面 (递推题)

很明显,当添加第n条直线时,为了使平面最多,则第n条直线要与前面n-1条直线都相交,切没有任何三条线交于一个点。
这样,第n条直线一共有n-1个交点。我们知道,增加n个焦点,则增加n+1个平面。
所以n条直线分割平面最大数是1 + 1 + 2 + 3 + … + n = (n2 + n + 2) / 2
熟悉了线分割平面,现在,我们再来看看,每次增加的不是一条直线,而是两条相互平行的线,那又如何呢?
当第N次添加时,前面已经有2N-2条直线了,按我们上面讨论的知道,第N次添加时,第2N-1条直线和第2N条直线各能增加2(n-1)+1个平面。
所以第N次添加增加的面数是2[2(n-1) + 1] = 4n - 2 个。因此,总面数应该是1 + 4n(n+1)/2 - 2n = 2n2 + 1
现在我们再来看如果把每次加进来的平行边让它们一头相交,情况又如何呢?
我们看到,平面1、3已经合为一个面,既少了一个面。因此,每当一组平行线相交后,就会减少一个面。
因此,本题所要求的折线分割平面,自然就是上面求的的平行线分割平面数减去N。
即2n2 - n + 1

#include <stdio.h>
int main(void)
{
    int n, i;
    scanf("%d", &i);
    while (i-- && scanf("%d", &n))
        printf("%d\n", 2*n*n-n+1);
    return 0;
}

2049 不容易系列之(4)——考新郎

  • 依然是错排问题,方法见2048题。但这里还要从N个新郎中找出M个冤大头。

  • 思路:组合+错排公式

  • 错排公式:f[i]=(i-1)*(f[i-1]+f[i-2]) (f[1]=0; f[2]=1;)

      #include<stdio.h>
      #include<string.h>
      #include<stdlib.h>
      long long f[25];
      long long C(int n,int m)  //组合公式
      {
      	int i;
      	long long sum1,sum2;
      	sum1=sum2=1;
      	for(i=n;i>=(m+1);i--)
      		sum1*=i;
      	for(i=1;i<=(n-m);i++)
      		sum2*=i;
      	return sum1/sum2;
      }
      int main()
      {
      	int n,m,t;
      	long long ans;
      	f[1]=0;
      	f[2]=1;
      	for(i=3;i<=20;i++)  //错排
      		f[i]=(i-1)*(f[i-1]+f[i-2]);
      	//scanf("%d",&t);
      	while(scanf("%d%d",&n,&m)!=EOF)
      	{
      		//scanf("%d%d",&n,&m);
      		ans=C(n,m)*f[m];
      		printf("%lld\n",ans);
      	}
      	return 0;
      }
    

2048 神、上帝以及老天爷

有参加晚会的人员都将一张写有自己名字的字条放入抽奖箱中;
然后,待所有字条加入完毕,每人从箱中取一个字条;
最后,如果取得的字条上写的就是自己的名字,那么“恭喜你,中奖了!”

  • N张票的所有排列可能自然是Ann = N!种排列方式
    现在的问题就是N张票的错排方式有几种。
    首先我们考虑,如果前面N-1个人拿的都不是自己的票,即前N-1个人满足错排,现在又来了一个人,他手里拿的是自己的票。
    只要他把自己的票与其他N-1个人中的任意一个交换,就可以满足N个人的错排。这时有N-1种方法。
    另外,我们考虑,如果前N-1个人不满足错排,而第N个人把自己的票与其中一个人交换后恰好满足错排。
    这种情况发生在原先N-1人中,N-2个人满足错排,有且仅有一个人拿的是自己的票,而第N个人恰好与他做了交换,这时候就满足了错排。
    因为前N-1个人中,每个人都有机会拿着自己的票。所以有N-1种交换的可能。
    综上所述:f(n) = (i - 1) * [f(n - 1) + f(n - 2)]

      #include<stdio.h>
     int main()
     {
         long long a[21],s;
         int c,i,n;
         a[1]=0;
         a[2]=1;
         for(i=3; i<21; i++)
             a[i]=(i-1)*(a[i-1]+a[i-2]);
         scanf("%d",&c);
         while(c--)
         {
             int n;
             scanf("%d",&n);
             s=1;
             for(i=2; i<=n; i++)
                 s=s*i;
             printf("%.2f%%\n",a[n]*100.0/s);
         }
         return 0;
     }
    

2047 阿牛的EOF牛肉串

这道题的难点是如何找好规律:
对于第n项:
当f(n-1)为o时。有两种可能即E,F;
当f(n-1)不是o,时,有三种可能E,O,F;
从图中能够看出:
f(n-1)为o的情况=f(n-2)-(第n-1,n-2项都为o的情况,即f(n-2)3-f(n-1))=f(n-1)-2f(n-2);
f(n-1)不是0的情况=2f(n-2);
所以:f(n)=2
( f(n-1)-2f(n-2) )+3( 2f(n-2) )
=2
f(n-1)+2*f(n-2);

#include<stdio.h>
int main()
{
 int n,i;
 __int64 a[66]={0,3,8};//由于后面的数值是直接与n相应的 所以a[0]应该复制为零,而不是三
 for(i=3;i<66;i++)
 {
  a[i]=2*a[i-1]+2*a[i-2];
 }
 while(~scanf("%d",&n))
 {
  printf("%I64d\n",a[n]);
 }
 return 0;
}
//由于牵扯到的数值较大 所以用__int64型

2046 骨牌铺方格

第N张牌的排列可以又N-1张牌的排列再在末尾加上一张竖的牌。这样依然合法。
也可以在N-2张合法排列的牌后面加上两张横着放的牌(如果竖着放就和上面一种重复了)。
所以f(n) = f(n-1) + f(n-2)
即又是一个斐波那契数列。

#include <math.h>
#include <stdio.h>	
int main(void)
{
    int i;
    __int64 d[51] = {1, 1, 2,};
    for (i = 3; i < 51; i++)
    d[i] = d[i-1] + d[i-2];
    while (scanf("%d", &i) != EOF)
     printf("%I64d\n", d[i]);
    return 0;
}

2045 不容易系列之(3)——LELE的RPG难题 (递推问题)

数组F[i]保存i个方格有多少种填涂方法。
n个方格可以由n-1个方格和n-2个方格填充得到。
比如,在一涂好的n-1个格子里最后再插入一个格子,就得到了n个格子了。
因为已经填好n-1的格子中,每两个格子的颜色都不相同。
所以只能插入一种颜色。而n-1个格子一共有F[n-1]种填涂方法。所以从n-1格扩充到n格共有F(n-1)种方法。
若前n-1不合法,而添加一个后变成合法,即前n-2个合法,而第n-1个与第1个相同。
这时候有两种填法。
所以
f[n] = f[n-1] + 2 * f[n-2];
f[1] = 3;
f[2] = 6;
f[3] = 6

#include <math.h>
#include <stdio.h>

int main(void)
{
    int i;
    __int64 d[51] = {0, 3, 6, 6};

    for (i = 4; i < 51; i++)
        d[i] = d[i-1] + 2*d[i-2];
    while (scanf("%d", &i) != EOF)
        printf("%I64d\n", d[i]);

    return 0;
}

2044 一只小蜜蜂…

  • 一只蜜蜂可以往下一格走,也可以往图的右边走。
    比如:
    蜜蜂在1格里,它可以往2、3两格里爬。
    蜜蜂在6格里,它可以往7、8两格里爬。
    所以在第n格里蜜蜂可以爬到第n+1, n+2格子里。
    因此,这又是一个斐波那契数。

      #include <stdio.h>
      	int main(void)
      	{
      	    int i, j, n;
      	    __int64 d[51] = {1, 1, 2,};
      	
      	    for (i = 3; i < 51; i++)
      	        d[i] = d[i-1] + d[i-2];
      	    scanf("%d", &n);
      	    while (n-- && scanf("%d%d", &i, &j) != EOF)
      	        printf("%I64d\n", i > j ? 0 : d[j-i]);
      	
      	    return 0;
      	}
    

2043 密码

1).密码长度大于等于8,且不要超过16。
(2).密码中的字符应该来自下面“字符类别”中四组中的至少三组。
这四个字符类别分别为:
1.大写字母:A,B,C…Z;
2.小写字母:a,b,c…z;
3.数字:0,1,2…9;
4.特殊符号:~,!,@,#,$,%,^;

#include <ctype.h>
#include <stdio.h>
int main(void)
{
    int n, a[6];
    char c;
    scanf("%d%*c", &n);
    while (n--)
    {
        a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = 0;
        while ((c = getchar()) != '\n')
        {
            if (isupper(c))
                a[0] = a[5]++;
            else if (islower(c))
                a[1] = a[5]++;
            else if (isdigit(c))
                a[2] = a[5]++;
            else
                a[3] = a[5]++;
        }
        if (a[0]) a[4]++;
        if (a[1]) a[4]++;
        if (a[2]) a[4]++;
        if (a[3]) a[4]++;
        puts(a[4] > 2 && a[5] > 7 && a[5] <17 ? "YES" : "NO");
    }
    return 0;
}

2042 不容易系列之二

收费员就将他的羊拿走一半,看到老汉泪水涟涟,犹豫了一下,又还给老汉一只。巧合的是,后面每过一个收费站,都是拿走当时羊的一半,然后退还一只,等到老汉到达市场,就只剩下3只羊了。
算一下老汉最初有多少只羊吗?
输入数据第一行是一个整数N,下面由N行组成,每行包含一个整数a(0<a<=30),表示收费站的数量。

直拉从后往前推,不解释。

#include <stdio.h>
int main()
{
    int n,i,j,a,sum;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a);
        sum=3;
        for(j=1;j<=a;j++)
            sum=(sum-1)*2;
        printf("%d/n",sum);
    }
}

2041 超级楼梯

有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?
由题目可知,每次只能走一级或两级。
因此从第一级走上第二级只能走一步,只有1种走法。
从第一级走上第三级,可以从第一级直接走两步,也可以从第二级走一步。有2种走法
走上第n级,可以从第n-1级走一步上来,也可以从第n-2级走两步上来。
即:
f(2) = 1
f(3) = 2
f(n) = f(n-1) + f(n-2) (n > 3)
是一个斐波那契函数。

#include <stdio.h>
int main(void)
{
    int i, n;
    __int64 m[41] = {0, 1};
    for (i = 2; i < 41; i++)
     m[i] = m[i-1] + m[i-2];
    scanf("%d", &n);
    while (n-- && scanf("%d", &i))
    printf("%I64d\n", m[i]);
    return 0;
}

2040 亲和数 !!!易考

古希腊数学家毕达哥拉斯在自然数研究中发现,220的所有真约数(即不是自身的约数)之和为:
1+2+4+5+10+11+20+22+44+55+110=284。
而284的所有真约数为1、2、4、71、 142,加起来恰好为220。人们对这样的数感到很惊奇,并称之为亲和数。一般地讲,如果两个数中任何一个数都是另一个数的真约数之和,则这两个数就是亲和数。
你的任务就编写一个程序,判断给定的两个数是否是亲和数

	#include <stdio.h>
	int A(int n)
	{
	    int i,sum = 1;
	    for (i = 2; i <= n / 2; i++)
	     if (n % i == 0)
	     sum += i;
	    return sum;
	}
	int main(void)
	{
	    int n, a, b;
	    scanf("%d", &n);
	    while (n-- && scanf("%d%d", &a, &b))
	     puts(A(a) == b && A(b) == a ? "YES" : "NO");
	    return 0;
	}

2039 三角形

给定三条边,请你判断一下能不能组成一个三角形。 读数据的时候,不要忘了三条边要用实数型,而不是整型。_

#include <stdio.h>
int main(void)
{
	int n;
	double a, b, c;
	scanf("%d", &n);
	while (n-- && scanf("%lf%lf%lf", &a, &b, &c))
		puts(a + b > c && a + c > b && b + c > a ? "YES" : "NO");
	return 0;
}				
#include <stdio.h>
int main(void)
{
	int n;
	double a, b, c;
	scanf("%d", &n);
	while (n-- && scanf("%lf%lf%lf", &a, &b, &c))
	puts(a + b > c && a + c > b && b + c > a ? "YES" : "NO");
	return 0;
}

2037 今年暑假不AC

你会合理安排吗?(目标是能看尽量多的完整节目)
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。

  • 贪心

      #include <stdio.h>
      #include <algorithm>
      using namespace std;
      struct node 
      {
      	int t1;//电视开始时间 
      	int t2;//电视的结束时间 
      }a[105]; 
      int cmp(node u,node v)//对节目按照结束时间从小到大排序,如果结束的时间相同,则按照开始的 
      {//时间从大到小的排序! 
      	if(u.t2==v.t2)//为什么要将开始的时间从大到小排序呢?是因为如果结束时间相同的话,开始的 
      		return u.t1>v.t1;//越迟,看节目的时间越短,你就能尽可能的多看电视! 
      	return u.t2<v.t2;//例如:2-3,3-4,2-4,你肯定会看2-3,3-4的两个电视,而不看2-4这个电视 
      }
      int main()
      {
      	int n,i,j,k,t;
      	while(scanf("%d",&n)&&n)
      	{
      		for(i=0;i<n;i++)//有n个开始和结束时间,将时间输入 
      			scanf("%d%d",&a[i].t1,&a[i].t2);
      		sort(a,a+n,cmp);//对时间进行排序 
      		for(i=1,t=a[0].t2,k=1;i<n;i++)//如果开始 的时间比他这个结束的时间迟,则就k++ 
      		{
      			if(a[i].t1>=t)//说明这个电视你能够看 
      			{
      				t=a[i].t2;
      				k++;
      			}
      		}
      		printf("%d\n",k);//k代表能看的电视的个数! 
      	}
      	return 0;
      }
    

2036 改革春风吹满

可以利用多边形求面积公式:
S = 0.5 * ( (x0y1-x1y0) + (x1y2-x2y1) + … + (xny0-x0yn) )
其中点(x0, y0), (x1, y1), … , (xn, yn)为多边形上按逆时针顺序的顶点。

面积S△OAB = SABCD - S△OAD - S△OBC

·SABCD = (y0 + y1) × (x0 - x1) ÷ 2
·S△OAD = x0 × y0 ÷ 2
·S△OBC = (-x1) × y1 ÷ 2
S△OAB = (x0 × y0 + x0 × y1 - x1 × y0 - x1 × y1 - x0 × y0 + x1 × y1) ÷ 2
= (x0 × y1 - x1 × y0) ÷ 2
公式成立。同理你可以算出其他情况也能符合这个公式。
2.假设该公式对于n个顶点的多边形成立。即:
S = 0.5 * ( (x0y1-x1y0) + (x1y2-x2y1) + … + (xny0-x0yn) )
在这里插入图片描述

#include<stdio.h>
int main()
{
    int n,i,j;
    double x[200],y[200],add;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)return 0;
        for(i=1;i<=n;i++)
            scanf("%lf%lf",&x[i],&y[i]);
        add=0;
        x[n+1]=x[1];y[n+1]=y[1];
        for(i=1;i<=n;i++)
            add=add+x[i]*y[i+1]-x[i+1]*y[i];
        printf("%.1lf\n",add/2);
    }
}

2035 人见人爱A^B

求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”

#include <stdio.h>
int main(void)
{
    int a;
    int b;
    int i;
    int sum;
    while (scanf("%d%d", &a, &b), a || b)
    {
        sum = a;
        for (i = 1 ; i < b ; i++)
         sum = (sum * a) % 1000;
        printf("%d\n", sum % 1000);
    }
    return 0;
}

2034 人见人爱A-B

  • A-B求的是两个集合的差,就是做集合的减法运算。

  • A中的元素减去B中有的
    直接用C语言去模拟一个集合,然后每读入一个数字,做一次遍历,如果找到就删除。最后才排一次序输出。

      #include <stdio.h>
      #include <stdlib.h>
      
      int cmp(const int *a, const int *b)
      {
          return *a - *b;
      }
      
      int main(void)
      {
          int n, m, i, j;
          int s[101];
          
          while (scanf("%d%d", &n, &m), m+n)
          {
              for (i = 0; i < n; i++)
                  scanf("%d", s + i);
              for (i = 0; i < m; i++)
              {
                  scanf("%d", s + n);
                  for (j = 0; s[j] != s[n]; j++);
                  if (j != n) s[j] = s[--n];
              }
              qsort(s, n, sizeof(int), cmp);
              for (i = 0; i < n; i++)
                  printf("%d ", s[i]);
              printf(n ? "\n" : "NULL\n");
          }
          
          return 0;
      }
    

2033 人见人爱A+B

  • 这个题目的A和B不是简单的整数,而是两个时间,A和B 都是由3个整数组成,分别表示时分秒,比如,假设A为34 45 56,就表示A所表示的时间是34小时 45分钟 56秒。

  • 我们平时用的是十进制,规则是逢10进1,而时间是六十进制,就是逢60进1位。
    本题就是让你做一个60进制的加法运算。

      #include <stdio.h>
      
      int main(void)
      {
          int n, i;
          int t[6];
          scanf("%d", &n);
          while (n--)
          {
              for (i = 0 ; i < 6 ; i++)
                  scanf("%d", t + i);
              t[1] += (t[2] + t[5]) / 60;
              t[2] = (t[2] + t[5]) % 60;
              t[0] += (t[1] + t[4]) / 60;
              t[1] = (t[1] + t[4]) % 60;
              t[0] += t[3];
              printf("%d %d %d\n", t[0], t[1], t[2]);
          }
          return 0;
      }		
    

2032 杨辉三角

  • 因为f(i, j) = f(i-1, j) + f(i-1, j-1),所以我们在编程的时候,完全可以只开一个一维数组。
    从i倒退到1,执行A[j] += A[j-1];这样就得到第i行的结果了~

法一:传统二维数组的方法

	#include <stdio.h>
	int main() {
	    int a[100][100] ;
	    int i,j,n;
	    while(scanf("%d",&n)!=EOF) {
	        for(i=1 ; i<=n; i++) {
	            for(j=1; j<=i; j++) {
	                if(j==1)
	                    a[i][j]=1;
	                else
	                    a[i][j]=a[i-1][j-1]+a[i-1][j];
	            }
	        }
	        for(i=1; i<=n; i++) {
	            for(j=1; j<=i; j++) {
	                printf("%d",a[i][j]);
	                if(j!=i)
	                    printf(" ");
	            }
	            printf("\n");
	        }
	        printf("\n");
	    }
	    return 0;
	}

法二:一维数组的方法

#include <stdio.h>
#include <string.h>
int main(void)
{
    int i, j, n;
    int YanHui[32];
    while (scanf("%d", &n) != EOF)
    {
        memset(YanHui, 0, sizeof(YanHui));
        YanHui[0] = 1;
        for (i = 0 ; i < n ; i++)
        {
            printf("%d", 1);
            for (j = i ; j ; j--)
                YanHui[j] += YanHui[j - 1];
            for (j = 1 ; j <= i ; j++)
                printf(" %d", YanHui[j]);
            putchar('\n');
        }
        putchar('\n');
    }
    return 0;
}

2031 进制转换

输入一个十进制数N,将它转换成R进制数输出。

  • 【数制换算的一般方法】
    1.把r进数转换成十进制数,只要把r进制数写成r的各次幂的和的形式。然后按十进制计算结果。(这里r是大于1的自然数)
    例如: (205.21)8 = 2 × 82 + 0 × 81 + 5 × 80 + 2 × 8-1 + 1 × 8-2
    2.把十进制换成r进制,可以把十进制化成r的各次幂(各次幂的系数小于r而大于或等于0的整数)的和,从最高次幂起各次幂的系数就是依次的r进制从左到右各个数位上的数字。

  • A.当十进制数是整数时,采用“r除取余”法。即用数r除十进整数。取它的每次余数。
    例如:把(746)10化为一个八进制的数。
    得到(746)10 = (1352)8

  • B.当十进制是小数时,采用“r乘取整”法,即用数r乘十进制小数,每乘一次取一次整数,直至小数部分变成零为止。
    例如:把(0.8125)10化为二进制。
    得到(0.8125)10 = (0.1101)2
    C.把r1进制数转换成r2进制数,一般可以先把r1进制数转换成十进制数,再从十进制数转换成r2进制数。

  • 从上面的算法可以看出,数制转换需要逆序输出,就需要用到栈。所以我们直接用递归调用了。

      #include <stdio.h>
      #include <string.h>
      void ttor(int n, int r)
      {
          if (n)
          {
              ttor(n / r, r);
              printf("%c", n % r > 9 ? n % r - 10 + 'A' : n % r + '0');
          }
      }
      int main(void)
      {
          int n;
          int r;
          while (scanf("%d%d", &n, &r) != EOF)
          {
              if (n > 0)
                  ttor(n, r);
              else if (!n)
                  putchar('0');
              else
              {
                  putchar('-');
                  ttor(-n, r);
              }
              putchar('\n');
          }
          return 0;
      }
    

2030 汉字统计

汉字占双字节,高位的字节里都是 < 0,所以只要统计小于0的字符的个数

#include <stdio.h>
#include <string.h>

int main(void)
{
    int n;
    int count;
    char c;

    scanf("%d%*c", &n);

    while (n--)
    {
        count = 0;

        while ((c = getchar()) != '\n')
        {
            if (c < 0)
                count++;
        }

        printf("%d\n", count / 2); //汉字两个字节
    }

    return 0;
}

2029 Palindromes_easy version

  • 回文串

      #include <stdio.h>
      #include <string.h>
      
      int main(void)
      {
      	int n, len, i;
      	char s[1024];
      	
      	scanf("%d%*c", &n);
      	
      	while (n--)
      	{
      		gets(s);
      		len = strlen(s);
      		for (i = 0; i <= len / 2; i++)
      		{
      			if (s[i] != s[len - 1 - i])
      				break;
      		}
      		puts(s[i] != s[len - 1 - i] ? "no" : "yes");
      	}
      	
      	return 0;
      }
    

2028 Lowest Common Multiple Plus

  • n个数的最小公倍数 这里 还是用辗转相除法

      #include<stdio.h>
      
      typedef unsigned long UL;
      
      UL gcd(UL u, UL v)
      {
          int remainder;
          
          remainder = u % v;
          while(remainder)
          {
              u = v;
              v = remainder;
              remainder = u % v;
          }
          return v;
      }
      
      UL lcm(UL u, UL v)
      {
          return u * v / gcd(u, v);
      }
      
      int main(void)
      {
          int n;
          UL u;
          UL res;
          
          while (scanf("%d", &n) != EOF)
          {
              res = 1;
      
              while (n--)
              {
                  scanf("%lu", &u);
                  res = lcm(res, u);
              }
      
              printf("%lu\n", res);
          }
      
          return 0;
      }
    

2027 统计元音

统计每个元音字母在字符串中出现的次数。

  • 也许字母会有大小写之分,记得用**tolower()或toupper()**换成统一的格式就可以了 很重要的

  • tolower
    #include <ctype.h> int tolower( int ch );
    功能:函数字符ch的小写形式。
    toupper
    #include <ctype.h> int toupper( int ch );
    功能:函数字符ch的大写形式。

      #include <ctype.h>
      #include <stdio.h>
      
      int main(void)
      {
          int n;
          int y[5];
          char c;
      
          scanf("%d%*c", &n);
          while (n--)
          {
              y[0] = y[1] = y[2] = y[3] = y[4] = 0;
              while ((c = getchar()) != '\n')
              {
                  switch (tolower(c))
                  {
                      case 'a':
                          y[0]++;
                          break;
                      case 'e':
                          y[1]++;
                          break;
                      case 'i':
                          y[2]++;
                          break;
                      case 'o':
                          y[3]++;
                          break;
                      case 'u':
                          y[4]++;
                          break;
                      default :
                          break;
                  }
              }
              printf("a:%d\n", y[0]);
              printf("e:%d\n", y[1]);
              printf("i:%d\n", y[2]);
              printf("o:%d\n", y[3]);
              printf("u:%d\n", y[4]);
              if (n) putchar('\n');
          }
      
          return 0;
      }
    

2026 首字母变大写

- 输入一个英文句子,将每个单词的第一个字母改成大写字母。
- 问题的关键在于如何判断为单词的首字母。

方法也不难,只要你判断当前字符为字母,而前一个为空格就可以了。
为了简单处理整个字符串的第一个字符。你可以让保存前一个字符的变量初始为空格。
这样就可以把判断规则统一起来了,不用特殊处理字符串的第一个字符。

  • isalpha
    函数:isalpha
    原型:int isalpha(int ch)
    用法:头文件加入#include (C语言使用<ctype.h>)
    功能:判断字符ch是否为英文字母,当ch为英文字母a-z或A-Z时,在标准c中相当于使用“isupper(ch)||islower(ch)”做测试,返回非零值(不一定是1),否则返回

      #include <ctype.h>
      #include <stdio.h>
      int main(void)
      {
          char t[128] = {' '};
          int i;
          while (gets(t + 1))
          {
              for (i = 1 ; t[i] ; i++)
                  putchar((isalpha(t[i]) && t[i-1] == ' ') ? toupper(t[i]) : t[i]);
              putchar('\n');
          }
          return 0;
      }
    

2025 查找最大元素

找到最大值后,只要用putchar()逐个输出,然后判断输出的是不是最大值,是就再输出一个(max),就是这么简单!
->abcdefgfedcba
xxxxx
<-abcdefg(max)fedcba
x(max)x(max)x(max)x(max)x(max)

#include <stdio.h>
int main(void)
{
    char t[128];
    char max;
    int i;
    while (gets(t))
    {
        for (max = i = 0 ; t[i] ; i++)
        {
            if (t[i] > max)
                max = t[i];
        }
        for (i = 0 ; t[i] ; i++)
        {
            putchar(t[i]);
            if (t[i] == max)
                printf("%s", "(max)");
        }
        putchar('\n');
    }
    return 0;
}

2024 C语言合法标识符

输入一个字符串,判断其是否是C的合法标识符。
isalpha
语法:
#include <ctype.h>
int isalpha( int ch );
功能:如果参数是字母字符,函数返回非零值,否则返回零值。
isalnum
语法:
#include <ctype.h>
int isalnum( int ch );
功能:如果参数是数字或字母字符,函数返回非零值,否则返回零值。

#include <ctype.h>
#include <stdio.h>
int main(void)
{
    int n, d, i;
    char sym[64];
    scanf("%d%*c", &n);
    while (n--)
    {
        gets(sym);
        if (sym[0] != '_' && !isalpha(sym[0]))
        {
            puts("no");
            continue;
        }
        for (d = i = 1 ; sym[i] ; i++)
        {
            if (!isalnum(sym[i]) && sym[i] != '_')
            {
                d = 0;
                break;
            }
        }
        puts(d ? "yes" : "no");
    }
    return 0;
}

2023 求平均成绩

假设一个班有n(n<=50)个学生,每人考m(m<=5)门课,求每个学生的平均成绩和每门课的平均成绩,并输出各科成绩均大于等于平均成绩的学生数量。

  • 输出要求

  • 对于每个测试实例,输出3行数据,第一行包含n个数据,表示n个学生的平均成绩,结果保留两位小数;第二行包含m个数据,表示m门课的平均成绩,结果保留两位小数;第三行是一个整数,表示该班级中各科成绩均大于等于平均成绩的学生数量。

      #include <stdio.h>
      #include <string.h>
      int main(void)
      {
          int n, m;
          int i, j;
          int t, d;
          int s[50];
          int c[5];
          int sc[50][5];
          while (scanf("%d%d", &n, &m) != EOF)
          {
              memset(s, 0, sizeof(s));
              memset(c, 0, sizeof(c));
              memset(sc, 0, sizeof(sc));
              for (i = 0 ; i < n ; i++)
              {
                  for (j = 0 ; j < m ; j++)
                  {
                      scanf("%d", &sc[i][j]);
                      c[j] += sc[i][j];
                      s[i] += sc[i][j];
                  }
              }
              for (i = 0 ; i < n ; i++)
                  printf("%.2lf%c", s[i] * 1.0 / m, i < n - 1 ? ' ' : ' \n');
              for (i = 0 ; i < m ; i++)
                  printf("%.2lf%c", c[i] * 1.0 / n, i < m - 1 ? ' ' : ' \n');
              for (t = i = 0 ; i < n ; i++)
              {
                  for (d = 1, j = 0 ; j < m ; j++)
                  {
                      if (sc[i][j] < 1.0 * c[j] / n)
                      {
                          d = 0;
                          break;
                      }
                  }
                  if (d) t++;
              }
              printf("%d\n\n", t);
          }
          return 0;
      }
    

2022 海选女主角

输入行列 代表这个女猪脚的坐标,选择一个绝对值最大的人当作猪脚。

  • 虽然这题算法简单,但是会有一个陷阱!
    我们知道,有符号long型能表示的范围是-2147483648 ~ 2147483647。你会发现。负数的范围其实比正数大。
    所以,如果你直接用long型,然后用abs来取绝对值,就可能造成数据溢出。你可以自己试一下输出abs(-2147483648)的值。
    解决方法是可以用double型来替换它

      #include <math.h>
      #include <stdio.h>
      int main(void)
      {
          int i, j;
          int n, m;
          int x, y;
          double a, t
          while (scanf("%d%d", &n, &m) != EOF)
          {
              a = x = y = 0;
              for (i = 0 ; i < n ; i++)
              {
                  for (j = 0 ; j < m ; j++)
                  {
                      scanf("%lf", &t);
                      if (fabs(t) > fabs(a))
                      {
                          a = t;
                          x = i;
                          y = j;
                      }
                  }
              }
              printf("%d %d %.0f\n", x + 1, y + 1, a);
          }
      
          return 0;
      }
    

2021 发工资咯:)

这道题可以简化为给定面额,求需要的人民币的张数。
用的方法是贪心。这不难理解,用的人民币的面值越大,当然张数就越少。
输入数据包含多个测试实例,每个测试实例的第一行是一个整数n(n<100),表示老师的人数,然后是n个老师的工资。 n=0表示输入的结束,不做处理。

#include <stdio.h>
int main(void)
{
    int n, i, x, sum;
   
    while (scanf("%d", &n), n)
    {
        sum = 0;
        for (i = 0 ; i < n ; i++)
        {
            scanf("%d", &x);
            sum += x / 100;
            x %= 100;
            sum += x / 50;
            x %= 50;
            sum += x / 10;
            x %= 10;
            sum += x / 5;
            x %= 5;
            sum += x / 2;
            x %= 2;
            sum += x;
        }
        printf("%d\n", sum);
    }
    return 0;
}

2020 绝对值排序

输入n(n<=100)个整数,按照绝对值从大到小排序后输出。题目保证对于每一个测试实例,所有的数的绝对值都不相等。
- qsort(s,n,sizeof(s[0]),cmp);
- int cmp(const void *a, const void *b)

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int cmp(const int *a, const int *b)
{
    return abs(*b) - abs(*a);
}
int main(void)
{
    int n, i, x[101];	    
    while (scanf("%d", &n), n)
    {
        for (i = 0 ; i < n ; i++)
            scanf("%d", x + i);
        qsort(x, n, sizeof(int), cmp);
        for (i = 0 ; i < n ; i++)
            printf("%d%c", x[i], (i != n - 1 ? ' ' : '\n'));
    }	
    return 0;

}

2018 母牛的故事

有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?

  • 第n年的牛的来源有2中:
    第n-1年的牛
    第n-3年的牛所生的小牛
    而递推的出口是第1年为1头,第2年为2头,第3年为3头。 知道了递推的规律,就可以写出方程了:
    f(n) = f(n-1) + f(n-3); (n > 3)
    f(n) = n; (n <= 3)

      #include <ctype.h>
      #include <stdio.h>	
      int main(void)
      {
          int n, i;
          int fab[55] = {1, 2, 3, 4, 6};
          for (i = 5 ; i < 55 ; i++)
              fab[i] = fab[i - 1] + fab[i - 3];
          while (scanf("%d", &n), n)
          {
              printf("%d\n", fab[n - 1]);
          }
          return 0;
      }
    

2017 字符串统计

给定的一个字符串,统计其中数字字符出现的次数
2
asdfasdf123123asdfasdf
asdf111111111asdfasdfasdf
6
9
直接调用的函数:
#include <ctype.h>
int isdigit( int ch );

#include <ctype.h>
#include <stdio.h>

int main(void)
{
    int n, d;
    char c;	
    scanf("%d%*c", &n);
    while (n--)
    {
        for (d = 0 ; (c = getchar()) != '\n' ;)
        {
            if (isdigit(c)) d++;
        }
        printf("%d\n", d);
    }

    return 0;
}

2016 数据的交换输出

输入n(n<100)个数,找出其中最小的数,将它与最前面的数交换后输出这些数。

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

int main(void)
{
    int i, n;
    int f[100], m;
    
    while (scanf("%d", &n), n)
    {
        m = 0;
        for (i = 0 ; i < n ; i++)
        {
            scanf("%d", f + i);
            if (f[i] < f[m]) m = i;
        }
        swap(f[m], f[0]);
        for (i = 0 ; i < n ; i++)
            printf("%d%c", f[i], (i < n - 1 ? ' ' : '\n'));
    }
    
    return 0;
}

2015 偶数求和

  • 有一个长度为n(n<=100)的数列,该数列定义为从2开始的递增有序偶数,现在要求你按照顺序每m个数求出一个平均值,如果最后不足m个,则以实际数量求平均值输出该平均值序列

     #include <stdio.h>		 
      int main(void)
      {
          int n, m;
       
          while(scanf("%d%d", &n, &m) != EOF) {
              int sum=0, ai=2, count=0, i;
       
              for(i=1; i<=n; i++) {
                  sum += ai;
                  ai += 2;            // 第1项为2,公差为2
       
                  // 求和项达到m项,则计算平均值并输出
                  if( i % m == 0) {
                      count++;
                      if(count != 1)
                          printf(" ");
                      printf("%d", sum / m);
       
                      // 和清零
                      sum = 0;
                  }
              }
       
              // 最后一个平均值:如果n是m的倍数则最后一项已经输出,否则输出最后一项。换行。
              if(n % m == 0)
                  printf("\n");
              else
                  printf(" %d\n", sum / (n % m));
          }
       
          return 0;
      }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值