hihoCoder编程练习赛49
题目1 : 相似颜色
描述
在CSS中我们可以用井号(#)加6位十六进制数表示一种颜色,例如#000000是黑色,#ff0000是红色,#ffd700是金色。
同时也可以将六位颜色#RRGGBB简写为#RGB三位颜色。例如#000与#000000是相同的,#f00与#ff0000是相同的,#639与#663399是相同的。
对于两个颜色#abcdef和#ghijkl,我们定义其距离是(ab - gh)2 + (cd - ij)2 + (ef - kl)2。(其中ab, cd, ef, gh, ij, kl都是十六进制数,也即0~255的整数)
给定一个六位颜色#abcdef,请你求出距离它最近的三位颜色#rgb。
输入
#abcdef
其中abcdef是'0'-'9'或'a'-'f'。
输出
距离输入颜色最近的#rgb
- 样例输入
-
#40e0d0
- 样例输出
- #4dc
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 6 using namespace std; 7 8 const char Hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 9 10 int transform(char ch){ 11 if(ch >= '0' && ch <= '9')return ch-'0'; 12 if(ch >= 'a' && ch <= 'f')return ch-'a'+10; 13 } 14 15 int main() 16 { 17 string str; 18 while(cin>>str){ 19 int a = 16*transform(str[1])+transform(str[2]); 20 int b = 16*transform(str[3])+transform(str[4]); 21 int c = 16*transform(str[5])+transform(str[6]); 22 int aa = a / 17; 23 if(a-17*aa > 17*aa+17-a)aa += 1; 24 int bb = b / 17; 25 if(b-17*bb > 17*bb+17-b)bb += 1; 26 int cc = c / 17; 27 if(c-17*cc > 17*cc+17-c)cc += 1; 28 if(aa>=16)aa = 15; 29 if(bb >= 16) bb = 15; 30 if(cc >= 16) cc = 15; 31 cout<<"#"<<Hex[aa]<<Hex[bb]<<Hex[cc]<<endl; 32 } 33 34 return 0; 35 }
1 import java.io.BufferedInputStream; 2 import java.util.Scanner; 3 4 public class Main { 5 static final char[] hex = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 6 7 public static int transform(char ch) { 8 int res = 0; 9 if(ch >= '0' && ch <= '9')res = ch-'0'; 10 if(ch >= 'a' && ch <= 'f')res = ch-'a'+10; 11 return res; 12 } 13 14 public static void main(String[] args) { 15 // TODO Auto-generated method stub 16 Scanner cin = new Scanner(new BufferedInputStream(System.in)); 17 18 String str; 19 while(cin.hasNext()) { 20 str = cin.nextLine(); 21 int a = 16*transform(str.charAt(1))+transform(str.charAt(2)); 22 int b = 16*transform(str.charAt(3))+transform(str.charAt(4)); 23 int c = 16*transform(str.charAt(5))+transform(str.charAt(6)); 24 int aa = a / 17; 25 if(a-17*aa > 17*aa+17-a)aa += 1; 26 int bb = b / 17; 27 if(b-17*bb > 17*bb+17-b)bb += 1; 28 int cc = c / 17; 29 if(c-17*cc > 17*cc+17-c)cc += 1; 30 if(aa>=16)aa = 15; 31 if(bb >= 16) bb = 15; 32 if(cc >= 16) cc = 15; 33 System.out.println("#"+hex[aa]+hex[bb]+hex[cc]); 34 } 35 } 36 37 }
题目2 : 挑选子集
描述
给定N个整数A1, A2, ... AN,小Hi希望从中选出M个整数,使得任意两个选出的整数的差都是K的倍数。
请你计算有多少种不同的选法。由于选法可能非常多,你只需要输出对1000000009取模的结果。
输入
第一行包含三个整数N、M和K。
第二行包含N个整数A1, A2, ... AN。
对于30%的数据,2 ≤ M ≤ N ≤ 10
对于100%的数据,2 ≤ M ≤ N ≤ 100 1 ≤ K, Ai ≤ 100
输出
一个整数表示答案。
- 样例输入
-
5 3 2 1 2 3 4 5
- 样例输出
- 1
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #define ll long long 6 7 using namespace std; 8 9 const int N = 110; 10 const ll MOD = 1000000009; 11 ll arr[N], cnt[N], fact[N]; 12 13 ll pow(ll a, ll b)//快速幂 14 { 15 ll ans = 1; 16 while(b) 17 { 18 if(b&1)ans *= a, ans %= MOD; 19 a *= a, a %= MOD; 20 b>>=1; 21 } 22 return ans; 23 } 24 25 ll inv(ll x){ 26 return pow(x, MOD-2); 27 } 28 29 int main() 30 { 31 fact[0] = 1; 32 for(int i = 1; i < 105; i++) fact[i] = (fact[i-1]*i)%MOD; 33 int n, m, k; 34 while(cin>>n>>m>>k){ 35 for(int i = 0; i < n; i++) cin >> arr[i]; 36 sort(arr, arr+n); 37 memset(cnt, 0, sizeof(cnt)); 38 for(int i = 0; i < n; i++){ 39 for(int j = i; j < n; j++){ 40 if((arr[j]-arr[i])%k == 0)cnt[i]++; 41 } 42 } 43 ll ans = 0; 44 for(int i = 0; i < n; i++){ 45 if(cnt[i] < m)continue; 46 ans += ((fact[cnt[i]-1]*inv(fact[m-1]))%MOD * inv(fact[cnt[i]-m]))%MOD; 47 ans %= MOD; 48 } 49 cout<<ans<<endl; 50 } 51 52 return 0; 53 }
1 import java.io.BufferedInputStream; 2 import java.util.Scanner; 3 4 public class Main { 5 static final int N = 110; 6 static final long MOD = 1000000009; 7 8 static long pow(long a, long n) { 9 long ans = 1; 10 while(n != 0) { 11 if((n & 1) != 0) ans = ans*a%MOD; 12 a = a*a%MOD; 13 n >>= 1; 14 } 15 return ans; 16 } 17 18 static long inv(long x) { 19 return pow(x, MOD-2); 20 } 21 22 public static void main(String[] args) { 23 // TODO Auto-generated method stub 24 Scanner cin = new Scanner(new BufferedInputStream(System.in)); 25 int n, m, k, a; 26 long [] fact = new long[N]; 27 fact[0] = 1; 28 for(int i = 1; i < 105; i+=1) { 29 fact[i] = (long) (fact[i-1]*i%MOD); 30 } 31 while(cin.hasNext()) { 32 n = cin.nextInt(); 33 m = cin.nextInt(); 34 k = cin.nextInt(); 35 int[] cnt = new int[N]; 36 for(int i = 0; i < n; i+=1) { 37 a = cin.nextInt(); 38 cnt[a%k] += 1; 39 } 40 long ans = 0; 41 for(int i = 0; i < k; i+=1) { 42 if(cnt[i] >= m) 43 ans += (((fact[cnt[i]]*inv(fact[m]))%MOD*inv(fact[cnt[i]-m]))%MOD)%MOD; 44 } 45 System.out.println(ans); 46 } 47 48 } 49 50 }
题目3 : 矩阵迷宫
描述
给定一个NxN的方格矩阵迷宫,每个格子中都有一个整数Aij。最初小Hi位于迷宫左上角的格子A11,他每一步可以向右或向下移动,目标是移动到迷宫的出口——右下角ANN。
小Hi需要支付的代价包括路径中经过的所有格子中的整数之和,以及改变移动方向需要支付的代价。
小Hi第一次改变方向的代价是1,第二次的代价是2,第三次的代价是4,…… 第K次的代价是2K-1。
请你帮小Hi算出要离开迷宫代价最小的路径,并输出要支付的代价。
输入
第一行一个整数N。 (1 ≤ N ≤ 100)
以下N行每行N个整数,代表矩阵A。 (1 ≤ Aij ≤ 100)
输出
从左上角到右下角路径的最小的代价。
- 样例输入
-
3 1 3 5 1 1 2 5 1 1
- 样例输出
- 9
1 import java.io.BufferedInputStream; 2 import java.util.Scanner; 3 4 public class Main { 5 static final int N = 110; 6 7 static int [][] arr = new int[N][N]; 8 static int [][][][] dp = new int[N][N][N*2][2]; // dp[i][j][k][l]表示从l方向到达(i,j)点,拐了k次弯的最小代价,令l=0为从左到右,l=1为从上到下 9 static int INF = 0x3f3f3f3f; 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 Scanner cin = new Scanner(new BufferedInputStream(System.in)); 13 int n; 14 while(cin.hasNext()) { 15 n = cin.nextInt(); 16 for(int i = 1; i <= n; i++) { 17 for(int j = 1; j <= n; j++) { 18 arr[i][j] = cin.nextInt(); 19 } 20 } 21 for(int i = 1; i <= n; i++) 22 for(int j = 1; j <= n; j++) 23 for(int k = 0; k <= i+j; k++) 24 dp[i][j][k][0] = dp[i][j][k][1] = INF; 25 dp[1][1][0][0] = arr[1][1]; 26 dp[1][1][0][1] = arr[1][1]; 27 for(int i = 1; i <= n; i++) { 28 for(int j = 1; j <= n; j++) { 29 for(int k = 0; k <= i+j; k++) { 30 if(k > 16)continue; // 剪枝 31 dp[i][j+1][k][0] = Math.min(dp[i][j+1][k][0], dp[i][j][k][0]+arr[i][j+1]); 32 dp[i+1][j][k+1][1] = Math.min(dp[i+1][j][k+1][1], dp[i][j][k][0]+arr[i+1][j]+(int)Math.pow(2, k)); 33 dp[i+1][j][k][1] = Math.min(dp[i+1][j][k][1], dp[i][j][k][1]+arr[i+1][j]); 34 dp[i][j+1][k+1][0] = Math.min(dp[i][j+1][k+1][0], dp[i][j][k][1]+arr[i][j+1]+(int)Math.pow(2, k)); 35 } 36 } 37 } 38 int ans = INF; 39 for(int k = 0; k <= 2*n; k++) 40 for(int l = 0; l < 2; l++) 41 if(ans > dp[n][n][k][l]) 42 ans = dp[n][n][k][l]; 43 System.out.println(ans); 44 } 45 } 46 47 }