小学期acm训练第一发(简单数学题)

本文主要解析刘汝佳《算法竞赛入门经典》(第一版)第三章的数学杂题,涵盖UVA等多个oj平台的题目,涉及开方、棋盘问题、骰子旋转、字符串特征判断、等式构建、积木堆平均高度计算、蜗牛爬井、数字关系、完全二分图等算法问题,通过实例讲解并提供部分代码。
摘要由CSDN通过智能技术生成

这一部分为刘汝佳的《算法竞赛入门经典》(第一版)第三章的数学杂题部分,知识点的确比较杂,但还是以模拟为主。

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=43038#overview

题目分析:

A.UVA113 让你对一个高精度的数求开方,直接开高精模板好像会T,所以使用了JAVA(JAVA自带快速幂,所以算乘方的时候回比较快),在此基础上以1,p为边界进行二分查找。然而后来找了网上的题解才发现直接开double也是可以的(只考虑整数的时候精度误差可以忽略),看来以后还是大胆还是很重要的。

B.UVA10161 给你那个无限大的棋盘,再给你一个自然数n,问这个自然数在那个棋盘上第几行与第几列。方法是先判断n在哪两个完全平方数之间,这样可以大致确定n的范围,然后再分类讨论求出坐标即可。

C.UVA253 判断两个骰子是不是一样,那只需要判断其中一个骰子通过旋转是否能变得和另一个一样。又每个骰子有6个面,固定每个面朝上之后各有4种旋转方式(绕垂直的轴转一圈),酱紫共有4*6=24种情况,分别对比就好啦。

D.UVA621 简单模拟题,让你判断给你的字符串符合四种特征中的哪一个,注意按照顺序判断就行。

E.UVA10025 对1...n前加上正或负,使得结果为k。又给定整数k,求n的最小值,使得存在这样的等式。输入k时,如果k小于0,直接取相反数,因为所有正负号取反就可以得到原等式。然后假设所有的符号全部是正号,求出使得1+2+...+n>k的最小的n,然后判断奇偶性是否能满足条件(因为只要将若干个正号改成负号就相当于减去那些数的2倍),又因为是最小的n,所以这样的若干个数必定存在,再判断奇偶性就能解决了。最后不要忘记对0,1这样的边界数据特判。

F.UVA591 题意是让你算出最少移动多少次数可以把所有积木堆成同一高度,由于积木总数除以积木的堆数是整数,所以先把这个最后要达成的平均高度算出来,然后用所有比它高的积木堆的高度减去它,再求和即可。

G.UVA107 未AC

H.UVA573 传统的蜗牛爬井问题,白天向上爬U,晚上下滑D,每天向上爬的距离还要减去F%,井的高度是H,需要注意的地方除了第一天的临界情况外,还有蜗牛晚上向下滑,只有当绝对高度为负时,才算是failure。

I.UVA846 和E题有类似的思路,因为答案和起始的数字无关,只和两数之差有关,设两数之差为n,先求出最大的k,使得1+2+3+...+k<n,再贪心算出至少还需要加上多少步,注意分类讨论n=0的情况。

J.UVA10499 题目看起来很复杂,实际上就是让你算切成n块之后表面积增大的百分比,无坑,唯一难点在于看懂题目。

K.UVA10790 让你算完全二分图K_m,n的非边界的交点个数,可以枚举较小的情况猜,也可以直接根据边的条数找规律,注意多增加一条边会增加的交点的个数,具体规律见代码

L.UVA11044 题目大意:至少需要多少个3*3的纸片才能覆盖住所有除边界以外的所有点。方法:把边界去掉再向上整除。

M.UVA10719 未AC

N.UVA10177 直接找规律即可,求正方形与长方形的个数应该是小学的知识点,注意数据较大,需要开LL,不放心直接JAVA大数也是挺方便的

O.UVA10916 难点还是在于看懂题意,先根据年份可以推出对应的bit是多少,然后只需要求出最大的n,使得n!<2^bit数

P.UVA10970 题目大意:求出一块M*N的巧克力最少要切多少刀才能全部切开(不必考虑把两块巧克力叠起来再切的情况),数数就好啦,而且先切横着的还是先切竖着的最后结果都一样>_<

Q.UVA10014 给了一个递推式和若干已知量,让你求a_1。较为复杂的一个题,关键在于如何化简递推式。可以直接写成矩阵然后运用高斯消元求解。通过直接观察也可以发现将递推式全部写出来(令i=1,2,3,...,),然后分别将第一条式子*1,第二条式子*2,...,之后再累加可以得到a_n,再将所有递推式直接全部相加,又可以得到a_1和a_n的关系,解一下就好啦。


代码如下:

A.

import java.util.Scanner;
import java.math.BigInteger;
public class Main {
   
    public static void main(String[] args) {
   
        Scanner in = new Scanner(System.in);
        while(in.hasNext())
        {
   
            BigInteger b,c,low,high,key,temp;
            int a;
            a = in.nextInt();
            b = in.nextBigInteger();
            low = BigInteger.ONE;
            high = b;
            key = low.add(high).shiftRight(1);
            temp = key.pow(a);
            while(temp.compareTo(b) != 0)
            {
   
                if(temp.compareTo(b) == -1)
                {
   
                    low = key.add(BigInteger.ONE);
                    key = low.add(high).shiftRight(1);
                    temp = key.pow(a);
                }
                else
                {
   
                    high= key.subtract(BigInteger.ONE);
                    key = low.add(high).shiftRight(1);
                    temp = key.pow(a);
                }
            }
            System.out.println(key);
        }
    }
}


B.

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
   
    int n;
    cin >> n;
    while(n)
    {
   
            int x,y,xs,ys;
            if(abs(sqrt(n)-int(sqrt(n)))<1e-8)
            {
   
                if(int(sqrt(n)) % 2 == 0) cout << int(sqrt(n)) << " 1" << endl;
                else cout << "1 " << int(sqrt(n)) << endl;
                cin >> n;
                continue;
            }
            else if(abs(sqrt(n-1)-int(sqrt(n-1)))<1e-8)
            {
   
                if(int(sqrt(n-1)) % 2 == 0) cout << int(sqrt(n-1))+1 << " 1" << endl;
                else cout << "1 " << int(sqrt(n-1))+1 << endl;
                cin >> n;
                continue;
            }
            int p = int(sqrt(n));
            int q = p*p+p+1;
            //cout << p << " " << q << endl;
            if(p%2 == 0)
            {
   
                   if(n<=q)
                   cout << p+1 << " " << n-p*p << endl;
                   else cout << (p+1)*(p+1)-n+1 << " " << p+1<< endl;
            }
            else 
            {
   
                 if(n<=q)
                 cout << n-p*p << " " << p+1 << endl;
                 else cout << p+1 << " " << (p+1)*(p+1) << endl;
            }
            cin >> n;
    }
    return 0;
}


C.

#include <iostream>
#include <stdio.h>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <string>
#include <string.h>
#include <sstream>
#include <cctype>
#include <climits>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <iterator>
#include <algorithm>
#include <stack>
#include <functional>
/*int类型最大值INT_MAX,short最大值为SHORT_MAX
long long最大值为LONG_LONG_MAX*/
//cout << "OK" << endl;
#define _clr(x) memset(x,0,sizeof(x))
using namespace std;
const int INF = INT_MAX;
const double eps = 1e-8;
const double EULER = 0.577215664901532860;
const double PI = 3.1415926535897932384626;
const double E = 2.71828182845904523536028;
typedef long long LL;

int main()
{
   
    //freopen("sample.in", "r", stdin);
	//freopen("sample.out", "w", stdout);
	
	string s[25];
	while(cin >> s[1])
	{
   
		s[0] = s[1].substr(6,6);
		
		s[1] = s[1].substr(0,6);
		
		for (int i = 2;i<=24;i++) s[i] = s[1];
		
		s[5][0] = s[1][1];
		s[
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值