2016年1月29日 星期五

c108: 00305 - Joseph

內容 :
有一個惡名昭彰的故事:某部落酋長有n個俘虜(編號從1,2,3,……,n),他叫他們排成一個圈圈,然後開始數,第m 個人要被煮來吃掉(第一次從編號1的人開始數),按照此規則繼續下去,直到只剩下一個人,那一個人可以保留性命。例如:n=6, m=5則被吃掉的人的編號依序是5,4,6,2,3最號只有編號 1活了下來。Joseph 是個很聰明的人,他總是能挑到最後存留的位置,所以這件事才被披露出來。
現在假設共有2k個人,其中排在編號 1 到 k 的是好人,排在編號 k+1 到 2k 的是壞人,你的任務就是要找出一個最小的 m,使得在所有 k 個壞人被吃掉之前,沒有一個好人會被吃掉。
輸入說明 : 
每行一個整數k(0<k<14), k=0 代表輸入結束。
輸出說明 : 
根據輸入的 k,輸出 m
範例輸入 : help
3
4
0
範例輸出:
5
30
提示 : 
* Luck 貓翻譯
標籤:
出處: 
UVa305 (管理:)

import java.util.Scanner;

public class UVAc108 {

public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int[] table=new int[15];
int k;
for(int i=1;i<15;i++){
table[i]=solve(i);
}
while((k=sc.nextInt())!=0){
System.out.println(table[k]);
}

}
private static int solve(int k){
int people,suicide,m,count;
if(k==1) return 2;
people=2*k;
for(m=k;;m++){
if((m-1)%people>=k && (m-1)%people<2*k){         //k從0開始
suicide = (m-1)% people;
for(count=2;count<=k;count++){
               suicide = (suicide + m - 1)%(people-count+1);
               if(suicide<k||suicide>=2*k) break;
           }
           if(count==k+1)return m;
}
}
}

}

參考自:
http://edward15241.pixnet.net/blog/post/186310656-uva-305(%E2%98%85%E2%98%85%E2%98%85)joseph

2016年1月27日 星期三

c085: 00350 - Pseudo-Random Numbers

內容 :
電腦無法產生真正的亂數(Random numbers),但是經由某些程序電腦可以產生虛擬亂數(pseudo-random numbers)。亂數被使用在很多應用上,像是模擬等。
有一種常用的虛擬亂數產生方法:如果上一個亂數是L,那下一個亂數產生的方法是
(Z*L+I) mod M,在這裡Z、I、M都是常數。例如:假設Z=7 I=5 M=12。如果第一個亂數(通常叫做 seed)是 4 , 那我們可以產生以下幾個虛擬亂數:
我們可以發現,經過6個數字後,虛擬亂數的序列重複了,也就是說cycle length=6。
在這個問題中,你將會被給Z、I、M還有L(就是seed)的值(全部不大於9999),對每一組Z、I、M、L,要請你輸出所產生的虛擬亂數的cycle length。
請注意:cycle並不一定從seed開始。
輸入說明 : 
輸入的每一行有4個整數,依序為Z, I, M, L。(L一定比M小)
輸入的最後一行為4個0,代表輸入結束。
輸出說明 : 
對每一行輸入,輸出這是第幾組測試資料(連續數字,從1開始)和所產生的虛擬亂數的cycle length。
範例輸入 : help
7 5 12 4
5173 3849 3279 1511
9111 5309 6000 1234
1079 2136 9999 1237
0 0 0 0
範例輸出:
Case 1: 6
Case 2: 546
Case 3: 500
Case 4: 220
提示 : 
* 中文翻譯:Lucky 貓  
標籤:
出處: 
UVa350 (管理:)

import java.util.Scanner;

public class UVAc085 {

public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int i=1;
while(sc.hasNext()){
long Z=sc.nextLong(),I=sc.nextLong(),M=sc.nextLong(),L=sc.nextLong();
if(Z==0 && I==0 && M==0 && L==0) break;
long[] seed=new long[10000];
for(int j=0;j<10000;j++) 
seed[j]=-1;
seed[0]=L;
int count=1,j=0,d=0;
long total;
boolean flag=true;
while(true){
total=(Z*L+I)%M;
seed[count]=total;
L=total;
while(seed[j]!=-1){
if(seed[j]==L && j!=count){
flag=false;
d=j;
break;
}
j++;
}
count++;
j=0;
if(!flag) break;  
}
System.out.println("Case "+i+": "+(count-1-d));
i++;
}

}

}

c084: 00275 - Expanding Fractions

內容 :
這個題目要求你把兩個整數的商展開來。你應該清楚,有很多整數的商展開來以後會變成循環小數。你必須找出這些循環的部份。給你整數的商,你要印出它的小數展開式,當小數部份已經沒有了或是即將開始第一次重覆之前就要停止輸出。如果有循環,你要說明循環節有幾位數。
輸入說明 : 
會有多個輸入案例,每案例由同一行的兩個整數所組成。第一個整數代表分數的分子,第二則代表分母。本題目的分子永遠小於分母,分母永遠小於 1000。當分子分母同時為 0時,輸入結束。
輸出說明 : 
相對於每輸入案例,要輸出該分數的小數展開式,第一個字元是小數點。如果可以完全展開,印出完整的小數。如果是無限小數,就印到 (但不包含第一個重覆出現的循環節之前。
例如:4/11 = .3636363636...,應該印出 .36(注意,要找出最小的循環節。在此案例中 3636  363636 都是循環節,但是最短的循節是 36)
由於有些展開式會很長,請分行顯示,除了最後一行可以比較短外,每行必須剛好 50 字元,包含開始的小數點。
在最後一行的小數展開式之後,緊接著要說「This expansion terminates.  (完全展開)  或「The last n digits repeat forever.」,其中 n 代表循環節的位數。
所有案例的輸出之後都要有一行空行 (包括最後一個案例
實用小提示: 循環節的長度不會大於分母。
範例輸入 : help
3 7
345 800
112 990
53 122
0 0
範例輸出:
.428571
The last 6 digits repeat forever.
.43125
This expansion terminates.
.113
The last 2 digits repeat forever.
.4344262295081967213114754098360655737704918032786
885245901639
The last 60 digits repeat forever.
提示 : 
* 中文翻譯:Lucky 貓  
標籤:
出處: 
UVa275 (管理:)

import java.util.Scanner;

public class UVAc084 {

public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int n=sc.nextInt(),m=sc.nextInt();
if(n==0 && m==0) break;
int time=1,flag=0;
int[] math=new int[1001];
System.out.print(".");
math[n]=1;
while(true){
if(time%50==0)
 System.out.println();
   time++;
System.out.print(n*10/m);
n=n*10%m;
if(n==0) {flag=1;break;} 
if(math[n]!=0) break; 
 math[n]=time; 
}
if(flag==0){
System.out.println();
System.out.println("The last "+(time-math[n])+" digits repeat forever.");
}
else{
System.out.println();
   System.out.println("This expansion terminates."); 
}
}

}

}


c083: 00130 - Roman Roulette

內容 :
西元67年,在羅馬和猶太人的衝突中,史學家 Josephus 和其他40個人被關在一個洞穴中。羅馬人知道 Josephus 的下落後希望他能投效羅馬帝國。但是他的同伴們卻不允許他投降。所以Josephus 建議他們彼此殺害,一個接一個,被殺的順序就由命運決定。傳統上他們決定命運的方式為:大家圍成一個圓圈,從某個人開始算起,每算到 3 個人那個人就被殺掉,如此不斷下去,直到只剩一個人。後來 Josephus 成為唯一的存活者並投降羅馬。我們有興趣的是:Josephus 如何剛好是那個存活者?真的是運氣好,還是他事先在暗地裡用 41 顆石頭練習過,或者他有一個數學的方法可以知道要站在哪一個位置才能成為最後的存活者?
聽過這個故事後,你相當的憂心要是將來某一天你也面臨同樣的情況要怎麼辦。所以你決定用你的手上型電腦寫一個程式算出應該從那個人開始算起,你才可以成為那個最後唯一存活的人。
在這個問題中,你的程式必須能解決 Josephus 描述的另一種變形。有 n 個人排成一個圓圈,面向內,依順時鐘方向編號從 1 到 n。你的位置在 1 。殺人程序由編號 i 的人開始算起(順時鐘方向),直到算到第 k 個人,那個人立刻被殺掉。然後從這個被殺的人左邊的那個人再順時鐘方向算 k 個人,那個人必須負責埋葬剛才被殺的那個人,然後回去站在剛才被殺的那個人的位置。接下來從這個人的左邊那個人算起,第 k 個人又被殺掉,如此一直下去直到只剩下一個人為止。
例如:當 n=5, k=2, i=1, 那麼被殺的順序為 2, 5, 3, 1,存活者為4。
輸入說明 : 
輸入含有多組測試資料。
每組測試資料有2個整數 n, k 。你可以假設最多只有 100 個人。
若 n =  k = 0 時代表輸入結束。請參考Sample Input。
輸出說明 : 
對每組測試資料輸出一開始時應該從哪一個人算起(也就是 i),才能確保你是最後唯一的存活者。請記住:你的位置在 1。以上述的例子來看,必須由第 3 個人算起,最後存活的人才能是 1 。
範例輸入 : help
1 1
1 5
5 2
5 4
7 3
100 53
100 2
11 93
0 0
範例輸出:
1
1
3
5
1
13
83
2
提示 : 
* 中文翻譯:Lucky 貓  
標籤:
出處: 
UVa130 (管理:)

import java.util.Scanner;

public class UVAc083 {

public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int n=sc.nextInt(),k=sc.nextInt();
int man=n,i,temp=1,kill=0;
if(n==0 && k==0) break;
if(n==1){
System.out.println("1");
continue;
}
int[] arr=new int[n+1];
for(i=1;i<=n;i++) arr[i]=i;
while(man>1){
int count=0;
while(count<k){
if(temp>n) temp=1;
if(arr[temp]!=0)
count++;
temp++;
}
kill=temp-1;
arr[kill]=0;
count=0;
while(count<k){
if(temp>n) temp=1;
if(arr[temp]!=0)
count++;
temp++;
}
arr[kill]=arr[temp-1];
arr[temp-1]=0;
temp=kill+1;
man--;
}
if(arr[kill]==1){
System.out.println("1");
}else{
System.out.println((n-(arr[kill]-1)+1));
}
   }
}

}

2016年1月26日 星期二

c082: 00118 - Mutant Flatworld Expolrers

內容 :
給你一塊矩形土地的長寬,再依序給定每個機器人的初始位置狀況及一連串的指令集,你必須用你的程式求出每個機器人最後的位置狀況。
一個機器人的位置狀況包括了其坐標( x 坐標, y 坐標),和它面向的方向(用 N , S , E , W 來分別代表北、南、東、西)。至於一個機器人所收到的指令集,是一個由字母 ' L ' , ' R ' , 和 ' F ' 所構成的字串,其分別代表:
  • 左轉(Left):機器人在原地往左轉 90 度。
  • 右轉(Right): 機器人在原地往右轉 90 度。
  • 前進(Forward): 機器人往其面向的方向向前走一格,且不改變其面向之方向。
從坐標 (x,y) 走至 (x,y+1) 的這個方向我們定義為北方
因為此矩形土地是有邊界的,所以一旦一個機器人走出邊界掉落下去,就相當於永遠消失了。不過這個掉下去的機器人會留下「標記 ( scent ) 」,提醒以後的機器人,避免他們從同一個地方掉下去。掉下去的機器人會把標記,留在他掉落之前所在的最後一個坐標點。所以對於以後的機器人,當他正位在有標記的地方時,這個機器人就會忽略會讓他掉下去的指令。
輸入說明 : 
輸入裡的第一列有2個正整數,代表這個矩形世界右上角頂點的坐標,其中假設這個世界的左下角頂點坐標為 ( 0 , 0 )。
接下來是若干組有關機器人的初始位置狀況和指令集,每個機器人2列。第一列為位置狀況,包括了兩個整數和一個字元( N , S , E 或 W ),代表機器人初始的位置坐標以及機器人最初所面對的方向。第二列則是指令集,是一個由 ' L ' , ' R ' 和 ' F ' 所組成的字串。輸入以 end-of-file 作為結束。
各機器人是依序動作的,也就是說,直到一個機器人作完他全部的動作,下一個機器人才會開始動作。
所有機器人的初始位置皆會在矩形土地上,不會落在外面。任何坐標的最大值皆不會超過 50 。每個指令集的長度皆不會超過 100 個字元長。
輸出說明 : 
對於每一個機器人,你都必須輸出其最後所在的坐標和面對的方向。如果一個機器人會掉落出此世界外,你必須先輸出他在掉落前,最後的所在位置和面對的方向,再多加一個字: LOST 。
範例輸入 : help
5 3
1 1 E
RFRFRFRF
3 2 N
FRRFLLFFRRFLL
0 3 W
LLFFFLFLFL
範例輸出:
1 1 E
3 3 N LOST
2 3 S
提示 : 
* 中文翻譯:Lucky 貓  
標籤:
出處: 
UVa118 (管理:)


import java.util.Scanner;

public class UVAc082 {

public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int[][] DP=new int[100][100];  //掉落前的點
int MAX_X=sc.nextInt(),MAX_Y=sc.nextInt();
while(sc.hasNext()){
int robbot_x=sc.nextInt(),robbot_y=sc.nextInt();
boolean flag=true;                                     //有無掉落
String p=sc.next();
String str=sc.next();
//System.out.println(MAX_X+" "+MAX_Y+" "+robbot_x+" "+robbot_y+" "+p+" "+str);
if(str.equals("end-of-file"))
break;
for(int i=0;i<str.length();i++){
if(str.charAt(i)=='F'){
switch(p){
 case "N": robbot_y++; break;
 case "S": robbot_y--; break;
 case "E": robbot_x++; break;
 case "W": robbot_x--; break;
}
}
else if(str.charAt(i)=='L'){                          //往左轉
switch(p){
  case "N": p="W"; break;
  case "W": p="S"; break;
  case "S": p="E"; break;
  case "E": p="N"; break;
}
}
                else if(str.charAt(i)=='R'){                         //往右轉
                switch(p){
  case "N": p="E"; break;
  case "E": p="S"; break;
  case "S": p="W"; break;
  case "W": p="N"; break;
}
}
if(robbot_x<0 || robbot_y<0 || robbot_x>MAX_X || robbot_y>MAX_Y){
switch(p){
 case "N": robbot_y--; break;
 case "S": robbot_y++; break;
 case "E": robbot_x--; break;
 case "W": robbot_x++; break;
}
if(DP[robbot_x][robbot_y]==1){
continue;
}
flag=false;
DP[robbot_x][robbot_y]=1;
break;
}
}
if(flag){
System.out.println(robbot_x+" "+robbot_y+" "+p);
}else{
System.out.println(robbot_x+" "+robbot_y+" "+p+" LOST");
}
}

}

}

2016年1月23日 星期六

c094: 00661 - Blowing Fuses

內容 :
在家庭中我們偶爾會遇到這樣的狀況:在你打開一些家庭電器,如:電燈,電視,洗衣機……之後,當你打開微波爐的一瞬間,跳電了。因為電力使用過多超過保險 絲的最高負載。當然,這是一種安全措施,避免電線過熱燒掉房子。但是,如果在我們打開電器開關之前可以知道打開之後是否會造成保險絲燒掉,那不是很好嗎?
這個程式的任務就是要檢查打開某些電器開關之後,所有使用中的電器其總用電量是否會超過保險絲的容量。
輸入說明 : 
輸入資料包含好幾筆測試資料,每筆測試資料的第一行有3個整數 n、m、c, n 代表總共有多少個電器用品(n<=20), m 代表共有多少次電器用品開關的動作, c 代表保險絲的容量。
接下來的 n 行各有一個整數 i ,分別代表第1個電器,第2個電器......第n個電器用品使用時需要的電流。
再接下來的的m行,每行有一個介於 1 到 n 之間的整數 k,代表開/關第 k 個電器用品。注意:對同一個電器用品,第一次動作為開,第二次動作為關,依此類推。假設一開始時所有的電器用品的狀態均為關著的。
n = m = c = 0代表輸入結束
輸出說明 : 
對於每筆測試資料,如果保險絲燒掉,請輸出:Fuse was blown.
如果保險絲沒有燒掉,請輸出:Fuse was not blown. 並且輸出在開關的過程中出現的最大總用電量。
每組測試資料後請輸出一空白列。請參考Sample output。
範例輸入 : help
2 2 10
5
7
1
2
3 6 10
2
5
7
2
1
2
3
1
3
0 0 0
範例輸出:
Sequence 1
Fuse was blown.

Sequence 2
Fuse was not blown.
Maximal power consumption was 9 amperes.
提示 : 
* 中文翻譯:Lucky 貓  
標籤:
出處: 
UVa661 (管理:)

import java.util.Scanner;

public class UVAc094 {

public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int count=1;
while(sc.hasNext()){
int n=sc.nextInt(),m=sc.nextInt(),c=sc.nextInt();
int max=0,total=0;
if(n==0 && m==0 &&c==0) break;
int[] arr=new int[n+1];
for(int i=1;i<=n;i++)
arr[i]=sc.nextInt();
boolean[] off=new boolean[m+1];
for(int i=0;i<=m;i++)
off[i]=false;
for(int i=1;i<=m;i++){
int num=sc.nextInt();
if(off[num]==false){
total+=arr[num];
off[num]=true;
if(total>max)
max=total;
}else{
total-=arr[num];
off[num]=false;
}
}
if(c<total){
System.out.println("Sequence "+count);
System.out.println("Fuse was blown.");
}else{
System.out.println("Sequence "+count);
System.out.println("Fuse was not blown.");
System.out.println("Maximal power consumption was "+max+" amperes.");
}
count++;
}

}

}