1. 程式人生 > >小學期acm訓練第一發(簡單數學題)

小學期acm訓練第一發(簡單數學題)

這一部分為劉汝佳的《演算法競賽入門經典》(第一版)第三章的數學雜題部分,知識點的確比較雜,但還是以模擬為主。

題目連結: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 classMain {
    public static void main(String[] args) {
        Scannerin = new Scanner(System.in);
        while(in.hasNext())
        {
            BigIntegerb,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);
	
	strings[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[5][1] = s[1][5