2016ACM/ICPC亚洲区大连站-重现赛
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016ACM/ICPC亚洲区大连站-重现赛相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/search.php?field=problem&key=2016ACM%2FICPC%D1%C7%D6%DE%C7%F8%B4%F3%C1%AC%D5%BE-%D6%D8%CF%D6%C8%FC%A3%A8%B8%D0%D0%BB%B4%F3%C1%AC%BA%A3%CA%C2%B4%F3%D1%A7%A3%A9&source=1&searchmode=source
A.染色乱搞。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef struct Edge { 5 int to, next; 6 }Edge; 7 8 const int maxn = 1010; 9 int n, m, x, y; 10 int know[maxn], vis[maxn], color[maxn]; 11 int ecnt, head[maxn]; 12 Edge e[maxn*maxn]; 13 14 void init() { 15 ecnt = 0; 16 memset(head, -1, sizeof(head)); 17 memset(know, 0, sizeof(know)); 18 memset(vis, 0, sizeof(vis)); 19 memset(color, 0, sizeof(color)); 20 } 21 22 void adde(int u, int v) { 23 e[ecnt].to = v, e[ecnt].next = head[u]; 24 head[u] = ecnt++; 25 } 26 27 bool dfs(int u) { 28 for(int i = head[u]; ~i; i=e[i].next) { 29 int v = e[i].to; 30 if(color[v] == color[u]) return 0; 31 if(vis[v]) continue; 32 vis[v] = 1; 33 color[v] = 3 - color[u]; 34 if(!dfs(v)) return 0; 35 } 36 return 1; 37 } 38 39 int main() { 40 // freopen("in", "r", stdin); 41 int u, v; 42 while(~scanf("%d%d%d%d",&n,&m,&x,&y)) { 43 init(); 44 for(int i = 0; i < m; i++) { 45 scanf("%d%d",&u,&v); 46 adde(u, v); adde(v, u); 47 know[u] = know[v] = 1; 48 } 49 for(int i = 0; i < x; i++) { 50 scanf("%d", &u); 51 color[u] = 1; know[u] = 1; 52 } 53 for(int i = 0; i < y; i++) { 54 scanf("%d", &u); 55 color[u] = 2; know[u] = 1; 56 } 57 bool flag = 0; 58 for(int i = 1; i <= n; i++) { 59 if(!know[i]) { 60 flag = 1; 61 break; 62 } 63 } 64 if(flag) { 65 puts("NO"); 66 continue; 67 } 68 for(int i = 1; i <= n; i++) { 69 if(color[i]) { 70 vis[i] = 1; 71 if(!dfs(i)) { 72 flag = 1; 73 break; 74 } 75 } 76 } 77 for(int i = 1; i <= n; i++) { 78 if(!color[i]) { 79 vis[i] = 1; 80 color[i] = 1; 81 if(!dfs(i)) { 82 flag = 1; 83 break; 84 } 85 } 86 } 87 if(!flag) puts("YES"); 88 else puts("NO"); 89 } 90 return 0; 91 }
C.威佐夫博弈+大数,根号5用mathmatica跑出来的,其实可以用二分打表。
1 import java.math.BigDecimal; 2 import java.math.BigInteger; 3 import java.math.MathContext; 4 import java.math.RoundingMode; 5 import java.util.Scanner; 6 7 public class Main { 8 9 public static void main(String[] args) { 10 Scanner in = new Scanner(System.in); 11 BigDecimal n, m; 12 BigDecimal sqrt5 = new BigDecimal("2.2360679774997896964091736687312762354406183596115257242708972454105209256378048994144144083787822749695081761507737835"); 13 while(in.hasNextBigDecimal()) { 14 n = in.nextBigDecimal(); m = in.nextBigDecimal(); 15 if(m.equals(n.max(m))) { 16 BigDecimal x = n; 17 n = m; 18 m = x; 19 } 20 BigDecimal k = n.subtract(m); 21 BigDecimal p = new BigDecimal(1); 22 n = p.add(sqrt5).multiply(k); 23 n = n.divide(new BigDecimal(2)); 24 if(n.toBigInteger().equals(m.toBigInteger())) System.out.println("0"); 25 else System.out.println("1"); 26 } 27 } 28 }
二分打sqrt(5)
1 import java.math.BigDecimal; 2 import java.math.BigInteger; 3 import java.math.MathContext; 4 import java.math.RoundingMode; 5 import java.util.Scanner; 6 7 public class Main { 8 public static BigDecimal Get(BigDecimal x) { 9 BigDecimal lo = new BigDecimal("0.000000000000000000000000000001"); 10 BigDecimal hi = x; 11 for(int i = 0; i < 1000; i++) { 12 BigDecimal mid = lo.add(hi).divide(new BigDecimal("2.0")); 13 BigDecimal mid2 = mid.multiply(mid); 14 if(mid2.max(x).equals(mid2)) hi = mid; 15 else lo = mid; 16 } 17 return hi; 18 } 19 public static void main(String[] args) { 20 Scanner in = new Scanner(System.in); 21 BigDecimal n, m; 22 BigDecimal sqrt5 = Get(new BigDecimal(5)); 23 while(in.hasNextBigDecimal()) { 24 n = in.nextBigDecimal(); m = in.nextBigDecimal(); 25 if(m.equals(n.max(m))) { 26 BigDecimal x = n; 27 n = m; 28 m = x; 29 } 30 BigDecimal k = n.subtract(m); 31 BigDecimal p = new BigDecimal(1); 32 n = p.add(sqrt5).multiply(k); 33 n = n.divide(new BigDecimal(2)); 34 if(n.toBigInteger().equals(m.toBigInteger())) System.out.println("0"); 35 else System.out.println("1"); 36 } 37 } 38 }
D.找到规律gcd(a,b)=gcd(x,y)以后,就是解方程了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 LL a, b, x, y; 6 7 LL gcd(LL x, LL y) { 8 return y == 0 ? x : gcd(y, x % y); 9 } 10 int main() { 11 // freopen("in", "r", stdin); 12 while(~scanf("%I64d%I64d",&a,&b)) { 13 LL g = gcd(a, b); 14 LL k = b * g; 15 if(a * a - 4 * k < 0 || (LL)sqrt(a*a-4*k) != sqrt(a*a-4*k)) puts("No Solution"); 16 else { 17 LL delta = (LL)sqrt(a * a - 4 * k); 18 printf("%I64d %I64d\\n", (a-delta)/2, (a+delta)/2); 19 } 20 } 21 return 0; 22 }
F.考虑让整个数列a最长,那么就是公差为1的等差数列,这时候一定会有不够或者超过x的情况。这时候就把多余的部分从后往前+1补齐。问题就变成在这样一个数列里找到最长的不大于x的个数。由于有取模,所以除法用逆元来做。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 LL exgcd(LL a, LL b, LL &x, LL &y) { 7 if(b == 0) { 8 x = 1; 9 y = 0; 10 return a; 11 } 12 else { 13 LL ret = exgcd(b, a%b, x, y); 14 LL tmp = x; 15 x = y; 16 y = tmp - a / b * y; 17 return ret; 18 } 19 } 20 21 LL inv(LL a, LL m) { 22 LL x, y; 23 exgcd(a, m, x, y); 24 return (x % m + m) % m; 25 } 26 27 const LL mod = (LL)1e9+7; 28 const int maxn = 60600; 29 LL f[maxn]; 30 int x; 31 32 void init() { 33 memset(f, 0, sizeof(f)); 34 f[0] = 1; f[1] = 1; 35 for(int i = 2; i < maxn; i++) { 36 f[i] = (f[i-1] * i) % mod; 37 } 38 } 39 40 int main() { 41 // freopen("in", "r", stdin); 42 init(); 43 int T; 44 scanf("%d", &T); 45 while(T--) { 46 scanf("%d", &x); 47 if(x <= 1) { 48 printf("%d\\n", x); 49 continue; 50 } 51 int lo = 2, hi = maxn; 52 int pos = 2; 53 while(lo <= hi) { 54 int mid = (lo + hi) >> 1; 55 LL s = (mid + 2) * (mid - 1) / 2; 56 if(s <= x) { 57 lo = mid + 1; 58 pos = max(pos, mid); 59 } 60 else hi = mid - 1; 61 } 62 x -= (pos + 2) * (pos - 1) / 2; 63 if(x == pos) printf("%I64d\\n", (f[pos]*inv(2,mod))%mod*(pos+2)%mod); 64 else if(pos == 0) printf("%I64d\\n", f[pos]); 65 else printf("%I64d\\n", f[pos+1]*inv(pos-x+1,mod)%mod); 66 } 67 return 0; 68 }
H.奇数就无所谓,偶数的话先手有优势。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int k; 5 6 int main() { 7 // freopen("in", "r", stdin); 8 while(~scanf("%d", &k)) { 9 if(k & 1) puts("0"); 10 else puts("1"); 11 } 12 return 0; 13 }
I.余弦定理求出第三条边,高用角的一半的余弦乘一下斜边,面积加起来。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 11; 5 const double pi = 3.141592653; 6 int n, d; 7 int th; 8 double ret; 9 10 double f(int th) { 11 return d*cos(pi*th/2.0/180.0)*sqrt(2.0*d*d-2.0*d*d*cos(pi*th/180.0))/2.0; 12 } 13 14 int main() { 15 // freopen("in", "r", stdin); 16 while(~scanf("%d%d",&n,&d)) { 17 ret = 0.0; 18 for(int i = 1; i <= n; i++) { 19 scanf("%d", &th); 20 ret += f(th); 21 } 22 printf("%.3lf\\n", ret); 23 } 24 return 0; 25 }
J.拆成四部分挨个看看是不是97。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 110; 5 int n; 6 int a; 7 8 int f(int x) { 9 int cnt = 0; 10 int q = 4; 11 while(q--) { 12 if((x % 256) == 97) cnt++; 13 x >>= 8; 14 } 15 return cnt; 16 } 17 18 int main() { 19 // freopen("in", "r", stdin); 20 while(~scanf("%d", &n)) { 21 int ret = 0; 22 for(int i = 1; i <= n; i++) { 23 scanf("%d", &a); 24 ret += f(a); 25 } 26 printf("%d\\n", ret); 27 } 28 return 0; 29 }
以上是关于2016ACM/ICPC亚洲区大连站-重现赛的主要内容,如果未能解决你的问题,请参考以下文章
2016ACM/ICPC亚洲区大连站-重现赛(感谢大连海事大学)(6/10)
HDU 5974 A Simple Math Problem(数学解方程)——2016ACM/ICPC亚洲区大连站-重现赛(感谢大连海事大学)