2020年10月30日 星期五

b127: 會議中心(Room)

 題目來源:https://zerojudge.tw/ShowProblem?problemid=b127

技巧:費式數列

題目老實說,看文字有點複雜😂😂😂😂😂😂😂,但仔細觀察圖面,不難發現其實是費式數列,這也是解題的一些心得,每當拿到一個新的題目,最快讓你了解題意的通常不會是題目敘述,多觀察輸出輸入,或是圖形化示例。


以下附上程式碼:

#include <iostream>
using namespace std;


int main() {
  cin.tie(0),cin.sync_with_stdio(0);
  int n = 0;
  int arr[46];
  arr[0] = 0;
  arr[1] = 1;
  arr[2] = 2;
  for(int i = 3; i < 46; i++) {
    arr[i] = arr[i-1] + arr[i-2];
  }
  int i;
  while(cin >> i) {
    cout << arr[i] << "\n";
  }
}

2020年10月29日 星期四

d411: 算了好久......

 題目來源:https://zerojudge.tw/ShowProblem?problemid=d411

技巧:大數運算


這題要注意的是,M值高達10^9999,這必然沒辦法用基本的數字運算來處理。



以下附上程式碼:

#include <iostream>
#include<string>
#include <math.h>
using namespace std;

int n;
void mod(string num , int m) {
  int check = 0;
  for(int i = 0; i < num.length(); i++) {
    check *= 10;
    check += num[i] - '0';
    check = check % m;
  }
  if(check == 0) {
    cout <<"YA!!終於算出"+num+"可被2的" + to_string(n)+"次整除了!!\n";
  }  else {
    cout << "可惡!!算了這麼久"+num+"竟然無法被2的"+to_string(n) + "次整除\n";
  }
  
}

int main() {
  cin.tie(0),cin.sync_with_stdio(0);
  int m;
  string num;
  while(cin >> num >> n) {
    m = pow(2 , n);
    mod(num , m);
  }
}


d356: NOIP2002 1.級數求和

 題目來源:https://zerojudge.tw/ShowProblem?problemid=d356


已知:Sn= 1+1/2+1/3+…+1/n,求給定任意K直,找出SN>K時,N為何


範例輸入       

    

範例輸出

2


簡易程式碼如下:

#include <iostream>
using namespace std;
int main() {
  cin.tie(0),cin.sync_with_stdio(0);
  double b = 1,c = 1,a = 1;
  cin >> a;
  while(b <= a) {
    c+=1;
    b += 1/c;
  }
  cout << c << "\n";
}

2020年10月20日 星期二

f314: 3. 勇者修煉 APCS 2020.10.17

 https://zerojudge.tw/ShowProblem?problemid=f314

APCS 2020.10.17

沒想到今年第三題就需要用到演算法,感覺這次的5分應該會比7月的考試更有鑑別度了。

50*10000的矩陣,每個點有三個方向,如果用DFS可能要做到海枯石爛才做得完。

仔細觀察一下,其實這題跟

https://zerojudge.tw/ShowProblem?problemid=a693

https://zerojudge.tw/ShowProblem?problemid=a694

吞食天地這兩題有87%像,如果等等程式碼看不太懂的話,建議可以先挑戰吞食天地的題組,這題我是每一行從左掃到右,從右掃到左,去找單行每個點的最佳解。(當然上走到下也要走)。

試著舉例:

第I個點的最佳解為:

max(從左走到第I-1個點+第I個點的經驗值 , 第I個點的經驗值 , 從右走到第I+1個點+第I個點的經驗值  , 從上面走到第I個點+第I個點的經驗值)。

每個點依循這原則,加上判斷一下臨界點就可以囉。


程式碼如下:

如果有問題歡迎留言或來信討論

import sys
ans=0-sys.maxsize
m,n=tuple([int(i) for i in input().split()])
MAP=[[int(j) for j in input().split()] for i in range(m)]
dp_left =[[ans for i in range(n)] for j in range(m)]
dp_right=[[ans for i in range(n)] for j in range(m)]
dp =[[ans for i in range(n)] for j in range(m)]

dp_right[0][0] = MAP[0][0]
dp_left[0][n-1] = MAP[0][n-1]
for i in range(1,n):
  dp_right[0][i] = max([dp_right[0][i-1] + MAP[0][i] , MAP[0][i]])
  dp_left[0][n-i-1] = max([dp_left[0][n-i] + MAP[0][n-i-1] , MAP[0][n-i-1]])
  dp[0][i] = max([dp_right[0][i] , dp_left[0][i]])
  dp[0][n-i-1] = max([dp_right[0][n-i-1] , dp_left[0][n-i-1]])

half = int(n/2)
for j in range(1,m):
  for i in range(0,n):
    if i == 0:
      dp_right[j][i] = dp[j-1][i]
    else:
      dp_right[j][i] = max([dp_right[j][i-1], dp[j-1][i]])
    dp_right[j][i] += MAP[j][i]

    if i == 0:
      dp_left[j][n-i-1] = dp[j-1][n-i-1]
    else:
      dp_left[j][n-i-1] = max([dp_left[j][n-i] , dp[j-1][n-i-1]])
    dp_left[j][n-i-1] += MAP[j][n-i-1]

    if i >= half:
      dp[j][i] = max([dp_right[j][i] , dp_left[j][i]])
      dp[j][n-i-1] = max([dp_right[j][n-i-1] , dp_left[j][n-i-1]])


print(max(dp[m-1]))

f313: 2. 人口遷移 APCS 2020.10.17

https://zerojudge.tw/ShowProblem?problemid=f313

APCS 2020.10.17

這題比較要注意的是,先遷徙,再加總,如果邊遷徙邊作加總會算錯的唷,這題測資很善良的讓你知道邊遷邊加是錯的,如果是我就不會這麼善良了^.^。




 





解題程式碼如下:

如果有任何問題歡迎留言或來信討論。

import sys
a = []
r,c,k,m = tuple([int(i) for i in input().split()])

for i in range(r):
  a.append([int(j) for j in input().split()])
for i in range(m):
  b = [[0 for _ in range(c)] for _ in range(r)]
  for j in range(r):
    for l in range(c):
      if a[j][l] != -1:
        temp = int(a[j][l] / k)
        if j-1 >= 0 and a[j-1][l] != -1:
          b[j][l] -= temp
          b[j-1][l] += temp
        if j+1 < r and a[j+1][l] != -1:
          b[j][l] -= temp
          b[j+1][l] += temp
        if l-1 >= 0 and a[j][l-1] != -1:
          b[j][l] -= temp
          b[j][l-1] += temp
        if l+1 < c and a[j][l+1] != -1:
          b[j][l] -= temp
          b[j][l+1] += temp
  for j in range(r):
    for l in range(c):
      if a[j][l] == -1: continue
      a[j][l] += b[j][l]


maxI = -1
minI = sys.maxsize
for i in range(r):
  for j in range(c):
    if a[i][j] == -1: continue
    if a[i][j] > maxI:
      maxI = a[i][j]
    if a[i][j] < minI:
      minI = a[i][j]

print(minI)
print(maxI)

f312. 1.人力分配 APCS 2020.10.17

APCS 2020.10.17第一題的題目:
其實近幾年題目的第一題考驗的都不是程式能力,而是閱讀能力,基本上第一題所需要用到的就是基本條件式與迴圈的結合,只要讀懂題意,相信都是可以做出來的。
題目就如上面所說,A1 A2 B1 B2 C1 C2由測資提供,X2跟X1則依據題目所提供的總人數有所變化,以總人數2人為例,則兩間工廠的人數有[0,2] , [1,1] , [2,0]這三種組合。


解題程式如下:

如果有不清楚的歡迎留言或直接寄信給我討論囉。

import sys
a,b,c = tuple([int(i) for i in input().split()])
a1,b1,c1 = tuple([int(i) for i in input().split()])
n = int(input())
maxValue = -1 * sys.maxsize
for i in range(n+1):
  y = a * i*i + b * i + c + a1*(n-i)*(n-i) + b1 * (n-i) + c1
  if y > maxValue:
    maxValue = y

print(maxValue)


h206. 強者就是要戰,但......什麼才是強者呢?

         這題是很好的遞迴問題,每次遞迴的時候都要帶入此次遞迴的左右邊界、及這次是要取區間最大還是取區間最小的flag。         完整程式如下: def t (l , r , isBig) : if l == r -1 : retur...