--- tags: Programming Practice --- NYCU GPE # NYCU GPE ## 22351 : Quirksome Squares 只要判斷完全平方數即可,少用pow函數 ```cpp=1 #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; int table[9] = {0,10,100,1000,10000,10000,1000000,10000000,100000000}; int main (void){ int n = 0 ; while (cin >> n){ for (int i= 0 ; i<table[n] ; i++){ int r = (i/table[n/2]) + (i%table[n/2]); if ( pow(r,2) == i ){ if (n==2) printf ("%02d\n" , i); if (n==4) printf ("%04d\n" , i); if (n==6) printf ("%06d\n" , i); if (n==8) printf ("%08d\n" , i); } } } return 0; } ``` ## 11028 : Digit Primes 判斷質數: 1. 除了 2、3 ,質數一定滿足 6N+1 或 6N+5 2. 只需要檢查 3~根號K ```cpp=1 #include<iostream> #include<cmath> using namespace std; int is_prime(int k){ if (k==0 || k==1) return 0; else if (k==2 || k==3) return 1; else{ int upper_bound = pow(k,0.5); if ((k-1)%6 == 0 || (k-5)%6 == 0){ for (int i = 3; i <= upper_bound ; i++){ if (k % i == 0) return 0; } } else{ return 0; } return 1; } } int digital_sum(int k){ int ans =0; while(k>0){ ans += k % 10; k = k /10; } return ans; } int main (void){ int ca = 0; cin >> ca; int M = 0 , N = 0; for (int idx = 0 ;idx<ca;idx++){ cin >> M >> N; int count = 0; for (int i = M ; i <= N ; i++){ int a = is_prime(i); if (a==1){ int b = is_prime(digital_sum(i)); if (b==1){ count++; } } } cout << count << endl; } return 0; } ``` ## 11017 : Longest Common Subsequence LCS: 建立DP Hint: arr 長寬都個多一 ```cpp=1 #include<iostream> #include<vector> #include<string> using namespace std; int main (void){ string M, N; while (1){ getline(cin , M); getline(cin , N); if (M=="" || N=="") break; vector < vector<int> > arr; for (int i = 0 ; i <= M.size() ; i ++){ vector<int> temp; for (int j = 0 ; j <= N.size() ; j++){ temp.push_back(0); } arr.push_back(temp); } for (int i =1 ; i <= M.size() ; i++){ for (int j=1 ; j <= N.size() ; j++){ if (M[i-1] == N[j-1]){ arr[i][j] = arr[i-1][j-1]+1; } else{ arr[i][j] = max(arr[i-1][j],arr[i][j-1]); } } } cout <<arr[M.size()][N.size()] <<endl; } return 0; } ``` ## 24731:Roads in the North ## 2015-09: Longest Increasing Subsequence ```cpp=1 #include <iostream> #include <vector> using namespace std; int main (void){ int n = 0; while ( cin >> n){ vector <int> arr; vector <int> dp; for (int i = 0 ; i < n ; i++){ int temp; cin >> temp; arr.push_back(temp); dp.push_back(1); } int ans = 0; for (int i = 0 ; i < arr.size() ; i++){ for (int j = 0 ; j < i ; j++){ if (arr[i] > arr[j]){ dp[i] = max (dp[i] , dp[j]+1); } } ans = max (ans , dp[i]); } cout << ans << endl; } return 0; } ``` ## 23681: Bachet's Game 因為stan 先開始,所以只針對stan的狀態 確保 j - k[i] >= 0 && status[j - k[i]] 狀態為輸 j 為石頭數量 k[i] 為拿法 ```cpp=1 #include<iostream> #include<vector> using namespace std; int main (void){ int n , m ; while(1){ cin >> n >> m ; vector <int> k; vector <int> status; for (int i = 0 ; i <= n ; i++){ status.push_back(0); } for (int i = 0; i < m ; i++){ int temp ; cin >> temp; k.push_back(temp); } for (int j = 1 ; j <= n ;j++){ for (int i = 0 ; i < m; i++){ if (j-k[i] >= 0 && status[j-k[i]]==0) status[j]=1; } } if (status[n]==1) cout << "Stan Wins" << endl; else{ cout << "Ollie Wins" << endl; } } } ``` ## 10675: Urn-ball Probabilities 题目要求所有抽取中,至少有一次抽到两个红球的概率 我们算出所有抽取中,每次都没有抽到两个红球的概率Q=(q1*q2*q3……qn),则1-Q为所求答案 另外要求出,每一次都抽到两个红球的概率,即P=(p1*p2*p3……pn) 但P这个数值必定非常小,所以题目只需要输出P小数点后有多少个连续的0 所以取log ```cpp=1 #include<iostream> #include<vector> #include<stdio.h> #include<cmath> using namespace std; int main (void){ double p=1 , q=1 , a=0; vector<double> ans; vector<int>c; for (long long i = 1 ; i <= 1000000 ; i++){ p = (1.0 / i) * ( 1.0 / (i+1) ); q *= 1.0-p; ans.push_back(1-q); a += log10(p); c.push_back(abs(a)); } int n; while(cin >> n){ if (n==0){ break; } printf("%.6f %d\n",ans[n-1],c[n-1]); } } ``` ## 10422:Is This Integration 畫輔助線,正三角形單一內角=60度 ```cpp=1 #include<iostream> #include<cmath> using namespace std; int main (void){ double n; double pi = M_PI; while (cin >> n){ if (n==0) break; double ans1 , ans2 , ans3; ans3 = ((n * n / 2.0) - ( n * n * pow(3,0.5) / 8.0) - (n * n * pi / 12.0) )*8 ; ans2 = ((n * n) - (n * n * pi / 4.0) - (ans3 / 2.0 ) )* 4; ans1 = n*n - ans2 - ans3; printf("%.3f %.3f %.3f\n",ans1,ans2,ans3 ); } } ``` ## 24461: Sum of Consecutive Prime Numbers 先建立質數表 從小的質數往上加,超過數值後從頭往下減 ```cpp=1 #include <iostream> #include <cmath> #include <vector> using namespace std; int judge_prime(int a){ if ( a==0 || a==1 ){ return 0; } else if ( a==2 || a==3){ return 1; } else { int upper_bound = pow(a,0.5); if ((a-1)%6 ==0 || (a-5)%6 ==0 ){ for (int i=2; i <= upper_bound ; i++){ if (a%i == 0 ) return 0; } } else{ return 0; } return 1; } } int main(){ vector <int> ptable; for (int i=2; i < 10000 ; i++){ if (judge_prime(i) == 1) ptable.push_back(i); } int test; while(cin >> test){ int sum=0,c=0,j=0; if (test == 0 ) break; for (int i = 0 ; test >= ptable[i] ; i++){ sum += ptable[i]; while(sum > test){ sum -= ptable[j]; j++; } if (sum == test) c++; } cout << c << endl; } } ``` ## 10500:Brick Wall Patterns 費氏數列 ```cpp=1 #include<iostream> using namespace std; int main (void){ long long DP[60]={0,1,2}; for (int i=3; i<59; i++){ DP[i] = DP[i-1] + DP[i-2]; } int n; while(cin >> n){ if (n==0) break; cout << DP[n] << endl; } return 0; } ``` ## 10471:COUNTING CHAOS 先檢查有沒有超過一天, 之後用窮局法依次檢查 ```cpp=1 #include<iostream> #include<stdio.h> #include<cstdlib> #include<cstring> using namespace std; int main (void){ int n; while(cin >> n){ if (n==0) break; int x ,y,n; scanf("%2d:%2d",&x,&y); int time; time = 60*x + y; char str[10]; while(1){ time++; if (time >= 1440) time=0; x = time / 60 ; y = time % 60; sprintf(str , "%02d%02d" , x ,y); sscanf(str, "%d", &n); sprintf(str, "%d", n); int flag =0; for (int i=0 , j=strlen(str)-1 ; i < j ; i++ , j--){ if (str[i] != str[j] ){ flag = 1; } } if (!flag){ printf("%02d:%02d\n",x,y); break; } } } } ``` ## 21944:Power Crisis +i mod j ```cpp=1 #include<iostream> #include<string> using namespace std; int main (void){ int n; int i; while (cin >> n){ n--; for (i = 1 ; i < n ;i++){ int turnoff = 0; for (int j = 1 ; j <= n ;j++){ turnoff = (turnoff+i) % j; } if (turnoff == 11) break; } cout << i << endl; } } ``` ## 10605:Count the Trees 從n+2 乘到 2n + 大數乘法 ```cpp=1 #include<iostream> using namespace std; const int MAX (1e8); long long ans[MAX]; int main (void){ int n; while(cin >> n && n!=0){ ans[0]=1; int len = 0; for (int i =n+2; i<=2*n; i++){ int temp =0; for (int j=0; j<=len;j++){ ans[j] = ans[j] *i + temp; temp = ans[j] / 100; ans[j] = ans[j] % 100; } if (temp>0){ len++; ans[len] = temp; } } for (int i = len ; i >=0 ; i --){ if (ans[i]==0){ cout << "00"; } else{ cout << ans[i]; } } cout << endl; } return 0; } ``` ## 10528:Light, more light 判斷是否為完全平方數 ```cpp=1 #include <iostream> #include <cmath> using namespace std; int main(void){ int n; while(cin >> n && n!=0){ int temp; temp = sqrt(n); if (temp * temp == n ){ cout << "yes" << endl; } else{ cout << "no" << endl; } } return 0; } ``` ## 11192:Simple Minded Hashing 題目的範圍過於浮誇 由於限制小寫英文字母,所以 a ~ z 有 26 個,而函數值為 1 + 2 + ... + 25 + 26 = 351 設一個 dp[i][j][k] i 代表選到哪一個字母 j 為 L ,代表字串長度 k 為 S ,代表函數值 字母 i 可選也可不選,所以 dp[i][j][k] = dp[i - 1][j][k] + dp[i - 1][j - 1][k - i] (前者不選 i ,後者選 i ) 同樣是事先全部建完表後再輸入資料 最後輸出答案 dp[26][L][S] ```cpp=1 #include <iostream> #include <cstring> using namespace std; int dp[27][27][352]; int main (void){ int L,S,ca; ca =1; memset (dp , 0, sizeof(dp)); dp[0][0][0] = 1; for (int i = 1 ; i <= 26 ; i++){ for (int j = 0 ; j <= i ; j++){ for (int k = 0 ; k <=351 ; k++){ dp[i][j][k] = dp[i - 1][j][k]; if (j && k >= i){ dp[i][j][k] += dp[i-1][j-1][k-i]; } } } } while (cin >> L >> S && L!=0 && S!=0){ cout << "Case " << ca << ": " << dp[26][L][S] << endl; ca++; } } ``` ## 22161:Euclid Problem 輾轉相除法 ```cpp=1 #include<iostream> using namespace std; int gcd(int a, int b , int &x, int &y){ if (a % b == 0){ x = 0; y = 1; return b; } else{ int r, tx,ty; r = gcd(b , a%b , tx , ty); x = ty; y = tx - a/b*ty; return r; } } int main (void){ int a,b,r,x,y; while(cin >> a >> b){ r = gcd(a,b,x,y); cout << x << " "<<y <<" "<< r << endl; } return 0; } ``` ## 10655:Sumsets ```cpp=1 #include <iostream> #include <algorithm> #include <map> using namespace std; int main(void){ int n , tmp; int nums[1002]; map<int,bool>subset; while(cin >> n){ if (n==0) break; for (int i = 0 ;i < n ;i++){ cin >> nums[i]; subset[nums[i]]=true; } sort(nums,nums+n,greater<int>()); bool found = false; int result; for (int i = 0; i<n ;i++){ for (int j = 0;j <n ;j++){ if (i==j) continue; for (int k = 0; k<n;k++){ if (k==i || k==j) continue; tmp = nums[i] - nums[j] - nums[k]; if (subset.find(tmp) != subset.end() && tmp != nums[i] && tmp != nums[j] && tmp != nums[k]) { found = true; result = nums[i]; i = j = k = n; } } } } if (found) cout << result << endl; else cout << "no solution" << endl; } return 0; } ``` ## 22181:Dollars dp[j] += dp[j-possible[i]]; ```cpp=1 #include<iostream> #include<stdio.h> using namespace std; int main (void){ long long dp[30005]={1}; long long possible[15] = {5,10,20,50,100,200,500,1000,2000,5000,10000}; for (int i = 0; i < 11 ; i++){ for (int j = possible[i] ; j <= 30000 ; j++){ dp[j] += dp[j-possible[i]]; } } int x,y; while (scanf("%d.%d",&x,&y)){ if(x==0 && y==0 ) break; printf ("%3d.%02d%17lld\n",x , y, dp[100*x+y]); } return 0; } ``` ## 22151:Big Mod 首先,要先知道數學式子:(A*B)%C = (A%C) * (B%C)。因此我就可以不用把B^P算完再去對M取餘數(避免超過變數範圍),但是如果是((((B%M)*B)%M)*B)%M…..這樣乘的話會TLE的,所以算次方請用次方除二相乘的遞迴來算次方,也就是 (B^P)%M = (B^(P/2)%M) * (B^(P/2)%M) 這樣遞迴。 ```cpp=1 #include<iostream> using namespace std; long long big_mod(long long B , long long P , long long m){ if (P==0) return 1; else if (P==1) return B%m; else { long long result = big_mod(B,P/2,m); if(P%2==1){ return result*result*B %m; } else{ return result*result%m; } } } int main (void){ long long B,P,m; while(cin >> B >> P >> m){ cout << big_mod(B,P,m) << endl; } return 0; } ``` ## 10582:Power Strings ```cpp=1 #include<iostream> #include<cstdio> #include<vector> using namespace std; int main (void){ string s; while(cin >> s && s!="."){ vector<int>failure; for (int i=0; i<s.length();i++){ failure.push_back(0); } for (int i=1, j=failure[0]=-1 ; i<s.length(); i++){ while(j>=0 && s[j+1] != s[i]){ j = failure[j]; } if(s[j+1] == s[i]){ j++; } failure[i] = j; } int repeat = s.length() - failure[s.length()-1]-1 ; if (s.length() % repeat == 0){ cout << s.length() / repeat << endl; } else{ cout << "1" << endl; } } } ``` ## 10416:Last Digit 0147656369 ```cpp=1 #include <iostream> #include <cstring> #include <cmath> using namespace std; int map[20]={0,1,5,2,8,3,9,2,8,7,7,8,4,7,3,8,4,1,5,4}; int main(void){ string n; while (cin >> n){ int len = n.length(); if (len=='0') break; int value = n[len-1]-'0'; if (len > 1){ value += (n[len-2]-'0')*10; } cout << (map[value%20] + value/20*4) % 10 << endl; } } ``` ## 10465:Necklace ```cpp=1 #include <bits/stdc++.h> using namespace std; int main(void){ double vt ,v0; while (cin >> vt >> v0){ int p = 0; double max = 0; for (int i = 1 ; i < vt ; i++){ if ((double)vt/i - v0 < 0 ) break; double sum = 0.3*i*sqrt((double)vt/i - v0); if (fabs(max - sum) <= 1e-10){ p=0; break; } else if (sum > max){ max = sum; p=i; } } cout << p << endl; } return 0; } ``` ## 23661:Bit Mask ```cpp=1 #include<bits/stdc++.h> using namespace std; int main (void){ unsigned int N , L ,U; while (cin >> N >> L >> U ){ int ans =0; for (int i =31 ; i >=0 ; i--){ if ((ans | (1<<i)) > U ) continue; if ((ans | (1<<i)) <= L || !(N & (1 << i))){ ans |= (1 << i); } } cout << ans << endl; } return 0; } ``` ## 10615:Divisibility dp[x+1][y] = y + k +- arr[i] =1 查看dp[n][0] ```cpp=0 #include<bits/stdc++.h> using namespace std; int dp[10001][101]; int arr[10001]; int main (void){ int t , n ,k; cin >> t ; for (int i =0 ;i < t ; i++){ cin >> n >> k; for (int j = 0 ; j <n ; j++){ cin >> arr[j]; } for (int j = 0 ; j <n ; j++){ arr[j] = abs(arr[j])%k; } memset(dp,0,sizeof(dp)); dp[0][0] = 1 ; for (int x = 0 ; x < n ; x ++){ for (int y = 0; y < k; y++){ if (dp[x][y]){ dp[x+1][(y+k+arr[x]) % k] =1; dp[x+1][(y+k-arr[x]) % k] =1; } } } if(dp[n][0]) cout << "YES"<< endl; else cout << "NO" << endl; // for (int x = 0 ; x < n+1 ; x ++){ // for (int y = 0; y < k; y++){ // cout << dp[x][y] <<" "; // } // cout << endl; // } } } ``` ## 10603:Cutting Sticks ```cpp=1 #include<bits/stdc++.h> using namespace std; int dp[55][55]; int a[55]; int solve(int x, int y){ if (~dp[x][y]) return dp[x][y]; if (x+1==y) return dp[x][y]=0; int cost = 999999; for (int i=x+1 ; i<y ;i++){ cost = min(cost,solve(x,i)+solve(i,y)); } return cost+a[y]-a[x]; } int main (void){ int L ,N ; while (cin >> L){ memset(dp,-1,sizeof(dp)); memset(a,0,sizeof(a)); cin >> N; for (int i=1 ; i<=N ; i++){ cin >> a[i]; } a[N+1] = L; cout << solve(0,N+1) << endl; } } ```