训练赛总结

A:

自守数是指一个数的平方的尾数等于该数自身的自然数。
例如:
25^2=625
76^2=5776
9376^2=87909376
请求出200000以内的自守数?

输入

输出
200000以内的自守数(包括0, 数之间用两个空格分开,末尾无空格) 

样例输入

样例输出
0  1  5  6  25  76  376  625  9376  90625  109376

#include<iostream>
#include<math.h>
using namespace std;
int main() {
    cout << "0" << "  ";
    for (long long  i = 1; i < 200000; i++) {
        //先判断i的位数
        int num = log10(i) + 1;
        int p = pow(10, num);

        if ((i * i) % p == i && i != 109376)  cout << i << "  ";
        if (i == 109376)  cout << "109376";
    }
    return 0;
}

知识点:

1.用于记录一个数的位数采用log10(n)+1;

2.用于算n的m次方使用pow(n,m);头文件包含<math.h>

B:

个球从100m高度自由落下,每次落地后反跳回原来高度的一半,再落下,再反弹.求它在第N次落地时共经过多少米?

输入

反弹的次数N

输出
小球经过的路程(保留四位小数)

样例输入
2
样例输出
200.0000

#include<bits/stdc++.h>
using namespace std;
int main() {
    double high = 100.00, s = 0.00;
    int N;
    cin >> N; //N为反弹的次数
    if (N == 0) s=0;
    if(N==1) s=100;
    else {
        s=100;
          while(N-1)
          {
              high=high/2;
              s=s+2*high;
              N--;
          }

        }
    cout<< fixed<<setprecision(4)<<s;
    return 0;
    


}

知识点:

1.用于算出结果包含有效位数时采用fixed

2.用于计算小数点后有几位时,同时采用fixed和setprecise(n)

C:

 

设有n个人围坐一圈并按顺时针方向从1到n编号,从第1个人开始进行1到m的报数,报数到第个m人,此人出圈,再从他的下一个人重新开始1到m的报数,如此进行下去直到所剩下一人为止。

输入格式

输入多行,每行2个数,分别表示n和m.

输出格式

计算每一行中最后剩下这个人的编号.

样例输入

复制

10 3

样例输出

复制

4
#include <iostream>
using namespace std;
int main() {
    int n, num;//n代表人数,num代表数的数字
    //最外层的循环代表持续输入
while    (cin >> n >> num)
{
    int a[n + 1];
    for (int i = 1; i <= n; i++)//将每个人都标记为0
        a[i] = 0;
    int p = 0;//p是前进的指针
    int m;
    int t;
    while (1) {//中层循环
        m = num;//每次将数的数字归为输入的数字
        while (m) {//内层循环
            p++;//p指针持续前进
            if (p > n) p = 1;//当p已经超过了人数时,就从第一个重新开始
            if (a[p] == 0) //当此时的p经过的人还没有数到特定数字的时候,m才需要减一
            {m--;if(m==0) a[p]=1;}
            //当m=0时是特定的情况比如输入的数字是2,1,此时来不及此层
            //循环外的赋值,会导致下面的统计人数出错为2人而继续下一个人的数数,所以这里提前赋值
            t = 0;//t用于统计场上剩余的人数
            for (int i = 1; i <= n; i++)
                if (a[i] == 0) t++;
            if (t == 1) break;//如果此时只剩下一个人,就不用再数,结束内层循环
                                  //num个人数完也退出循环
        }

        a[p]=1;//数到特定数字的人就标记为1
        //如果上面统计的只剩下1人
        if (t == 1) {
            int spec;
            for (int i = 1; i <= n; i++)
                if (a[i] == 0)  spec = i;//求出未数特定数字的那个人
            cout << spec;//输出他的序号
        }

        if (t == 1)     break;//如果场上剩余1人,结束中层循环
    }
    cout<<endl;//每次输出结果后跳到下一行
}
    return 0;
}

D:

挂盐水的时候,如果滴起来有规律,先是滴一滴,停一下;然后滴二滴,停一 下;再滴三滴,停一下...,现在有一个问题:这瓶盐水一共有VUL毫升,每一滴是D毫升,每一滴的速度是一秒(假设最后一滴不到D毫升,则花费的时间也 算一秒),停一下的时间也是一秒这瓶水什么时候能挂完呢?

输入
输入数据占一行,由VUL和D组成,其中0< D< VUL< 5000。

输出
请输出挂完盐水需要的时间。

样例输入
10 1
样例输出
13


#include<iostream>
using namespace std;
int main() {
    int VUL, D; //VUL表示总的毫升,D表示每一滴的毫升
    cin >> VUL >> D;
    int DBB = D; //用于固定每滴滴多少毫升
    int  t = 0, stoptime = 1;
    int n = 0; //t代表总时间 stoptime代表每次停止的时间,n代表每次滴的滴数
//进入循环,将瓶中的药水滴完
    while (VUL > 0) {
        VUL = VUL - D; //每次减去滴数*每滴的毫升数,第一次已经为1滴,后面每次依次累加
        n++;
        D = (n + 1) * DBB; //滴数*每滴的毫升数
        if (VUL <= 0)    t = t + n; //如果此时已经滴完,不加最后一段的停止时间
        else t = t + n + stoptime; //如果此时还有药水,还要进去下个停止时间继续滴,那就总时间加一个停止时间
    }
//如果此时瓶中的药水刚好为0,则直接输出
//如果此时药水为负数
    if (VUL < 0) {
        int etime = 0; //表示最后一段药水还没滴所需要的时间
        D = D - DBB;
        //因为此时多加了一个滴数导致VUL为负数,所以先回到上一个滴数*每滴的毫升数,举个例子比如21ml,每滴5毫升,那么每次分别为5,10,15,20,因为先减去15导致为负数,而减完n有加1
        //所以此时要先减一滴的毫升数为15
        VUL = VUL + D; //再把15加回来,也就是21-5-10=6,6-15=-9,所以要先把VUL重新赋值为-9+15=6然后再重新判断剩余药水所需要的时间
        //如果剩余药水量小于每滴的毫升数,比如16毫升,每滴5毫升,那顺序为5,10,此时的VUL==1,而1/5==0,但是还要1s,所以加上1
        if (VUL < DBB)   etime = VUL / DBB + 1;
        //如果刚好是每滴的毫升数的倍数,比如20毫升,每滴5毫升,那顺序为5,10,此时的VUL==5,VUL/DBB刚好为需要的时间,就不要再加1
        else if (VUL % DBB == 0)  etime = VUL / DBB;
        //如果此时的VUL比DBB大
        else   if (VUL > DBB) {
            //例子还是21毫升,每滴5毫升,那么每次分别为5,10,剩余6(6>5)
            //第一遍就是etime=0+6/5=1,VUL=1;
            //VUL已经小于DBB并且不为0,所以直接加1s退出循环
            //如果VUL==0,就不加,说明时间刚好例子就是VUL==20毫升,D==5毫升,此时etime=1,退出循环
            while (1) {
                etime = etime + VUL / DBB;
                VUL = VUL % DBB;
                if (VUL < DBB && VUL != 0) {
                    etime++;
                    break;
                }
                if (VUL == 0)  break;
            }
        }
        t = t - n + etime; // 此时的t时有加最后一段的时间的,n为最后一段的总时间,但是我们这种情况只需要最后一段的部分滴数,所以用当前时间-最后一段的时间再加上最后一段所需时间就是所需要的时间
    }
    cout << t;
    return 0;
}

 

E:

 

扫雷游戏你一定玩过吧!现在给你若干个n×m的地雷阵,请你计算出每个矩阵中每个单元格相邻单元格内地雷的个数,每个单元格最多有8个相邻的单元格。  0< n,m< =100

(注意两个矩阵之间应该有一个空行,由于oj的格式化这里不能显示出来)
 

输入格式

输入包含若干个矩阵,对于每个矩阵,第一行包含两个整数n和m,分别表示这个矩阵的行数和列数。接下来n行每行包含m个字符。安全区域用‘.’表示,有地雷区域用'*'表示。当n=m=0时输入结束。 

数据规模和约定
0< n,m< =100
 

输出格式

对于第i个矩阵,首先在单独的一行里打印序号:“Field  #i:”,接下来的n行中,读入的'.'应被该位置周围的地雷数所代替。输出的每两个矩阵必须用一个空行隔开。 

样例输入

复制

4  4 
*... 
.... 
.*.. 
.... 
3  5 
**... 
..... 
.*... 
0  0 

样例输出

复制

Field  #1: 
*100 
2210 
1*10 
1110 

Field  #2: 
**100 
33200 
1*100 
#include<iostream>
using namespace std;
int main() {
	int n, m, z = 0; //z代表张树,n代表行,m代表列
	char a[15][101][101];
	int b[50][2];
	int x = 0; //地雷表张数
	while (1) {
			cin >> n >> m;
			if (n == m && n == 0 && m == 0) break;
			z++;
			b[z][1]=n;
			b[z][2]=m;
			//输入地雷图
				for (int i = 1; i <= n; i++)
				for (int j = 1; j <= m; j++) 
				cin >> a[z][i][j];					
		}	
		while (x < z) {
			x = x + 1;
			cout << "Field #" << x << ":" << endl;
			for (int s = x; s <= x; s++) {
					int p=b[s][1];
						int q=b[s][2];
				for (int i = 1; i <= p; i++){
					for (int j = 1; j <= q; j++) 
					{
						if (a[s][i][j] == '*')cout << "*";
						else {
							int num = 0;
							for (int k = -1; k <= 1; k++)
								for (int g = -1; g <= 1; g++) {
									int nx = i + k;
									int ny = j + g;
									if (a[s][nx][ny] == '*'&&nx>0&&ny>0)  num++;
								}
							cout << num;	
						}
					
						if (j == q) cout << endl;
					}
				}		cout<<endl;
			}
		}
	return 0;
}

 F:

在 n * n 方阵里填入 1, 2, …, n * n, 要求填成蛇形。例如 n = 4 时方阵为: 

10 11 12 1 
9 16 13 2 
8 15 14 3 
7  6  5 4
输入格式
多组测试数据。
每组测试数据第一行输入方阵的维数,即 n 的值。(n <= 100)
输出格式
每组测试数据输出结果是蛇形方阵,方阵中每行每两个元素间空格,末尾不要有多余空格,每个方阵后空一行。
样例输入
3
样例输出
7 8 1 
6 9 2 
5 4 3
 

#include<iostream>
using namespace std;
int main()
{ 
int n; 
while(cin>>n){
   int a[n+1][n+1],b[n+1][n+1];
   int INF=10000001;
   for(int i=1;i<=n;i++)
   for(int j=1;j<=n;j++)
   b[i][j]=0; 
   //赋值
    int m=n*n;
    int i=1,h=1,j=n;
    int k=n;
    a[1][n]=1;
    b[1][n]=INF;
    if(n==0) cout<<"0"<<endl; 
    if(n!=1){ 
    while(m>1)
    {
     while(i<n){if(b[i+1][j]!=INF){a[i+1][j]=a[i][j]+1;i++;m--;b[i][j]=INF;}else break;}
     while(j>h){if(b[i][j-1]!=INF){a[i][j-1]=a[i][j]+1;j--;m--;b[i][j]=INF;}else break;}
     while(i>h){if(b[i-1][j]!=INF){a[i-1][j]=a[i][j]+1;i--;m--;b[i][j]=INF;}else break;}
     while(j<n){if(b[i][j+1]!=INF){a[i][j+1]=a[i][j]+1;m--;j++;b[i][j]=INF;}else break;}
     n--;h++;  
    }
    }
//输出蛇形表格
   for(int p=1;p<=k;p++)
   for(int q=1;q<=k;q++)
   {
       if(q==k)
       {
       cout<<a[p][q];
      cout<<endl;
       }
         else  cout<<a[p][q]<<" ";
   } 
 cout<<endl;
}
return 0;
}

 G:

//DP背包问题
给定N个物品,每个物品有一个重量W和一个价值V.你有一个能装M重量的背包.问怎么装使得所装价值最大.每个物品只有一个.

输入格式
输入的第一行包含两个整数n, m,分别表示物品的个数和背包能装重量。
以后N行每行两个数Wi和Vi,表示物品的重量和价值
输出格式
输出1行,包含一个整数,表示最大价值。
样例输入
3 5
2 3
3 5
4 7
样例输出
8

#include<iostream>
using namespace std;
const int L=5010; 
int w[L],v[L];
 int dp[L][L];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    cin>>v[i]>>w[i];
    for(int i=1;i<=n;i++)
    for(int j=0;j<=m;j++)
    { 
     dp[i][j]=dp[i-1][j];
    if(j>=v[i])  dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]);
    }
   cout<<dp[n][m];
   return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值