天天看點

算法競賽入門【碼蹄集進階塔335題】(MT2286-2290)

算法競賽入門【碼蹄集進階塔335題】(MT2286-2290)

文章目錄

  • 算法競賽入門【碼蹄集進階塔335題】(MT2286-2290)
  • 前言
  • 為什麼突然想學算法了?
  • 為什麼選擇碼蹄集作為刷題軟體?
  • 目錄
  • 1. MT2286 小碼哥的抽卡之旅1
  • 2. MT2287 抽獎機率
  • 3. MT2288 石子遊戲
  • 4. MT2289 誰會赢呢?
  • 5. MT2290 Game
  • 結語

前言

為什麼突然想學算法了?

> 用較為“官方”的語言講,是因為算法對計算機科學的所有分支都非常重要。 在絕大多數的計算機科學分支領域中,要想完成任何實質性的工作,了解算法的基礎知識并掌握與算法密切相關的資料結構知識是必不可少的。

> 但從實際而言,是因為當下快到了考研和找工作的年紀(ಥ_ಥ),無論走哪一條路,都不免需要一些相對豐富的算法知識,是故,便産生了一個暑假速成算法的計劃,可能對于像我這種算法競賽小白而言,幾乎很難,但我仍然還是想嘗試一下,畢竟,夢想還是要有的,萬一實作了呢?~( ̄▽ ̄~)~

算法競賽入門【碼蹄集進階塔335題】(MT2286-2290)

為什麼選擇碼蹄集作為刷題軟體?

碼蹄集,是在全國高等學校計算機教學與産業實踐資源建設專家委員會(TIPCC) 指導下建設的,其依托全國各大名校計算機系和清華大學出版社等機關的強大資源,旨在為計算機學習愛好者提供全面和權威的計算機習題。
算法競賽入門【碼蹄集進階塔335題】(MT2286-2290)

目錄

1. MT2286 小碼哥的抽卡之旅1

(1)題目描述

小碼哥最近迷上了一款抽卡遊戲。單抽出金的機率是0.6%,如果前89發都不出金,則90發必出金。小天目前存了一些抽數,想要你幫他算算他出金的機率。

格式

輸入格式: 一個整數n,表示小碼哥的抽數

.

輸出格式: 一個百分數p,表示出金的機率,保留六位小數(按所給樣例)

樣例1

輸入: 1

.

輸出: 0.600000%

(2)參考代碼

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int main() {
    int n;
    double get = 0, notget = 1 - get;
    cin >> n;
    for (int i = 0; i < n; i++) {
        get += notget * 0.006;
        notget = 1 - get;
    }
    printf("%.6lf%\n", get * 100);
    return 0;
}      

2. MT2287 抽獎機率

(1)題目描述

小碼哥正在進行抽獎,箱子裡有一紅一白兩小球,每次摸出一個球,摸到紅球中獎,如果中獎,就不再繼續抽獎;

如果未中獎(摸到白球),則往箱子裡補充一個白球(摸出的白球不放回),繼續抽獎,直到中獎,或者達到最大抽獎次數。

假設至多能抽獎M次,求當停止抽獎時,(中獎球數/摸出總球數)的期望。

格式

輸入格式: 第一行,一個整數M。

.

輸出格式: 保留到小數後六位。

樣例1

輸入: 4

.

輸出: 0.682292

(2)參考代碼

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int i,j,k,n,m,t;
double res;
int main() {
    cin>>n;
    for(i=1;i<=n;i++){
        res+=1.0/i/pow(2,i);
    }
    printf("%.6lf",res);
}      

3. MT2288 石子遊戲

(1)題目描述

小碼哥與小碼妹正在玩石子遊戲,遊戲規則是這樣的:桌上放有兩堆石子,雙方輪流取石子,輪到的一方隻能從數量較多的一堆裡取走另一堆的數量的正整數倍,把一堆石子取完的玩家獲勝(如果兩堆石子一樣多,可以任選一堆來取)。現在告訴你初始狀态下兩堆石子的數目,請你判斷若雙方采取最優政策,先手是否必勝。

格式

輸入格式: 一行,兩個正整數a, b 表示兩堆石子的數量,0<a,b ≤1×105。

.

輸出格式: 輸出一行,若先手必勝輸出YEs,否則輸出NO

樣例1

輸入格式: 13 10

.

輸出格式: NO

(2)參考代碼

#include <bits/stdc++.h>
using namespace std;
int dfs(int a,int b){
    if(a<b){
        int t=a;
        a=b;
        b=t;
    }
    int t=a%b;
    if(t==0) return 1;
    int ans=dfs(b,t);
    if(ans==0) return 1;
    if(t+b<a) ans=dfs(t+b,b);
    if(ans==0) return 1;
    return 0;
}
int main() {
    int a,b;
    cin>>a>>b;
    if(dfs(a,b)==1) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}      

4. MT2289 誰會赢呢?

(1)題目描述

小碼哥和小碼弟正在玩遊戲,他們都絕頂聰明。

開始時有一個整數n,二者輪流行動,每次行動可以在目前的n上減去其一個非1非n的因子。

若某一方無法進行操作則判其輸,小碼哥先手,誰會赢呢?

格式

輸入格式:

第一行一個正整數t表示資料組數。接下來t行,每行一個整數表示n

.

輸出格式: t行,每行輸出獲勝者

樣例1:

輸入:

4

1

4

12

69

.

輸出:

xiaomadi

xiaomage

xiaomage

xiaomadi

(2)參考代碼

import time
from typing import List, Tuple
from collections import deque, Counter
from queue import PriorityQueue
import math
from functools import lru_cache
#from sortedcontainers import SortedDict, SortedSet
import random
import copy
import sys
sys.setrecursionlimit(999999999)
MOD = 10**9 + 7
def get_prime(N):
    prime_vals = []
    flag = [True] * (N+1)
    for val in range(2, N+1):
        if flag[val]:
            prime_vals.append(val)
        for p_val in prime_vals:
            if val * p_val > N:
                break
            flag[val * p_val] = False
            if val % p_val == 0:
                break
    return prime_vals
primes = get_prime(100000)
def devide_prime(val):
    ans = []
    for i in primes:
        if i*i > val:
            break
        if val % i == 0:
            cnt = 0
            while val % i == 0:
                val //= i
                cnt += 1
            ans.append((i, cnt))
        if val == 1:
            break
    if val != 1:
        ans.append((val, 1))
    return ans
# 統計不等于1或者x自身的因子
def get_div(x):
    ret = devide_prime(x)
    ans = []
    def dfs(ii, val):
        nonlocal ans
        if ii == len(ret):
            if 1 < val < x:
                ans.append(val)
            return
        for i in range(ret[ii][1] + 1):
            dfs(ii + 1, val * (ret[ii][0] ** i))
    dfs(0, 1); return ans
def is_prime(x):
    if x <= 1:
        return False
    if x <= 3:
        return True
    i = 2
    while True:
        if i * i > x:
            break
        if i * i == x:
            return False
        if x % i == 0:
            return False
        i += 1
    return True
# 擷取2的次幂數
def get_2_cnt(x):
    cnt = 0
    while x > 0 and x & 1 == 0:
        cnt += 1
        x >>= 1
    return cnt
def main():
    # 先手是否必赢
    def dp(x):
        if x == 1 or is_prime(x):
            return False
        div = get_div(x)
        for v in div:
            if not dp(x - v):
                return True
        return False
    T = int(input())
    for _ in range(T):
        n = int(input())
        if n <= 10:
            ret = dp(n)
        else:
            # 規律:n是偶數且不是2的奇數次幂,則先手必勝
            cnt2 = get_2_cnt(n)
            ret = False
            if n % 2 == 0:
                if not (cnt2 & 1 == 1 and n == (1 << cnt2)):
                    ret = True
        print("Honcy" if ret else "Tak")
if __name__ == '__main__':
    main();      

5. MT2290 Game

(1)題目描述

小碼哥和小碼妹準備玩一個遊戲。有n堆石頭,每堆石頭個數為ai。小碼哥先手,每一回合玩家可以從n堆石頭中任選一堆移除。

勝負判定規則:

如果玩家移除一堆石頭之後,導緻所有移除的石頭數量之和是3的倍數,那麼該玩家輸。如果不滿足上一條,且移除後沒有剩餘的石頭,那麼小碼妹勝。(不關心于該回合是誰的)

保證兩者都是最聰明的。如果小碼哥勝則輸出1,否則輸出0。

請構造一個函數Game,然後傳入數組a,然後進行勝負的判斷。

格式

輸入格式: 第一行一個整數n(1≤n ≤105)第二行有n個整數a(1 ≤ai ≤104 )

.

輸出格式: 輸出1或者0

樣例1

輸入格式:

5

5 1 2 4 3

.

輸出格式: 0

(2)參考代碼

#include<bits/stdc++.h> 
/*
思路:不越獄的狀态好計算是以:越獄數=總的狀态數-不越獄的狀态數
其中 總的狀态數為:m^n
    不越獄的狀态數: m*(m-1)^(n-1) :隻有第一個可以選擇m個宗教,其他的隻能選和前一個不同的宗教是以是m-1種情況
這裡計算用了快速幂的方法。
*/
using namespace std;
long long p=1007;
long long qpow(long long x, long long y){
    if(y==0)
        return 1;
    if(y%2==1){
        return qpow(x, y - 1) * x % p;
    }else{
        long long t = qpow(x, y/2) % p;
        return t*t % p;
    }
}
int main( )
{
    long long m,n;
    cin>>m>>n;
    long long ans = qpow(m,n)-(m*qpow(m-1,n-1)%p);
    cout<<(ans+p)%p<<endl;//注意需要+p之後再取 %p,防止有負數
    return 0;
}      

結語

感謝大家一直以來的不斷支援與鼓勵,​​碼題集​​題庫中的進階塔350題正在逐漸更新,之後會逐漸跟進星耀,王者的題,盡請期待!!!

同時,也希望這些題能幫助到大家,一起進步,祝願每一個算法道路上的“苦行僧”們,都能夠曆經磨難,終成正果,既然選擇了這條路,走到了這裡,中途放棄,豈不是太過可惜?

繼續閱讀