第一周 7.10-7.16
假装自己复活辣。
7.10
CF 689 D Friends and Subsequences
二分。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 typedef long long LL; 6 const int maxn = 2e5 + 10; 7 int n, a[maxn], b[maxn]; 8 9 // RMQ 10 int M[maxn][20], m[maxn][20]; 11 void init() 12 { 13 for(int i = 1; i <= n; i++) M[i][0] = a[i]; 14 for(int j = 1; (1 << j) <= n; j++) 15 for(int i = 1; i + ( 1 << j ) - 1 <= n; i++) 16 M[i][j] = max(M[i][j-1] , M[i+(1<<j-1)][j-1]); 17 18 for(int i = 1; i <= n; i++) m[i][0] = b[i]; 19 for(int j = 1; (1 << j) <= n; j++) 20 for(int i = 1; i + ( 1 << j ) - 1 <= n; i++) 21 m[i][j] = min(m[i][j-1] , m[i+(1<<j-1)][j-1]); 22 } 23 24 int M_query(int l, int r) 25 { 26 int k = 0; 27 while( ( 1 << (k + 1) ) <= r - l + 1 ) k++; 28 return max(M[l][k], M[r-(1<<k)+1][k]); 29 } 30 31 int m_query(int l, int r) 32 { 33 int k = 0; 34 while( ( 1 << (k + 1) ) <= r - l + 1 ) k++; 35 return min(m[l][k], m[r-(1<<k)+1][k]); 36 } 37 38 int main(void) 39 { 40 scanf("%d", &n); 41 for(int i = 1; i <= n; i++) scanf("%d", a + i); 42 for(int i = 1; i <= n; i++) scanf("%d", b + i); 43 init(); 44 45 LL ans = 0LL; 46 for(int l = 1; l <= n; l++) 47 { 48 int t1, t2; 49 int L = l, R = n, mid; 50 51 if(M_query(l, n) < m_query(l, n)) R = n + 1; 52 else while(L < R) 53 { 54 mid = L + (R - L) / 2; 55 if(M_query(l, mid) < m_query(l, mid)) L = mid + 1; 56 else R = mid; 57 } 58 t1 = R; 59 60 L = l, R = n; 61 if(M_query(l, n) - 1 < m_query(l, n)) R = n + 1; 62 else while(L < R) 63 { 64 mid = L + (R - L) / 2; 65 if(M_query(l, mid) - 1 < m_query(l, mid)) L = mid + 1; 66 else R = mid; 67 } 68 t2 = R; 69 70 ans = ans + t2 - t1; 71 } 72 73 printf("%I64d\n", ans); 74 75 return 0; 76 }
7.12
HDU 5514 Frogs
因为每只步长为a[i]的青WA能踩到所有gcd(a[i], m)的倍数石头。
问题转化为给n个数,求能被这n个数中至少一个整除的数之和。
能被一个数整除的所有数之和是一个等差数列 容易计算,但是被多个数整除的数会重, 所以容斥一下。
因为所有gcd都是m的因子,先枚举m的所有因子,容易证明1e9内因子数目不会很多的。
比如 2^2 * 3^2 * 5 * 7 * 11 * 13 * 17 * 19 = 58198140,也就3^2 * 2^6 = 576个因子。
容斥的过程是 求 sigma能被一个gcd整除的数 - sigma能被两个gcd整除的数 +sigma能被三个gcd整除的数 ……
对于每个因子 算它的贡献的时候 它的所有倍数的贡献都被算过了 所以给倍数减去贡献就好了 负贡献也一样。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 const int maxn = 1e4 + 10; 8 int a[maxn], f[maxn], c[maxn]; 9 10 int gcd(int a, int b) 11 { 12 return a % b ? gcd(b, a % b) : b; 13 } 14 15 int main(void) 16 { 17 int T; 18 scanf("%d", &T); 19 for(int kase = 1; kase <= T; kase++) 20 { 21 int n, m; 22 scanf("%d %d", &n, &m); 23 for(int i = 1; i <= n; i++) scanf("%d", a + i); 24 25 memset(f, 0, sizeof(f)); 26 for(int i = 1; i * i <= m; i++) 27 { 28 if(m % i == 0) 29 { 30 f[++f[0]] = i; 31 if(i * i != m) f[++f[0]] = m / i; 32 } 33 } 34 sort(f + 1, f + 1 + f[0]); 35 36 memset(c, 0, sizeof(c)); 37 for(int i = 1; i <= n; i++) 38 { 39 int x = gcd(a[i], m); 40 for(int j = 1; j <= f[0]; j++) 41 if(f[j] % x == 0) c[j] = 1; 42 } 43 44 LL ans = 0LL; 45 for(int i = 1; i < f[0]; i++) 46 { 47 ans = ans + (LL) (m - 1) / f[i] * ((m - 1) / f[i] + 1) * f[i] / 2 * c[i]; 48 for(int j = i + 1; j <= f[0]; j++) 49 if(f[j] % f[i] == 0) c[j] -= c[i]; 50 } 51 52 printf("Case #%d: %I64d\n", kase, ans); 53 } 54 return 0; 55 }
7.13
HDU 5515 Game of Flying Circus
嘻嘻嘻
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 using namespace std; 5 6 int main(void) 7 { 8 int t; 9 scanf("%d", &t); 10 for(int kase = 1; kase <= t; kase++) 11 { 12 double T, V1, V2; 13 scanf("%lf %lf %lf", &T, &V1, &V2); 14 printf("Case #%d: ", kase); 15 if(V1 == 0) puts("No"); 16 else if(V1 >= V2) puts("Yes"); 17 else if(V1 * sqrt(2) > V2) 18 { 19 double tmp = V1 / V2 * V1 / V2; 20 double a = tmp - 1, b = 600 * tmp, c = a * 90000; 21 double x = (- b + sqrt(b * b - 4 * a * c)) / 2 / a; 22 if((x + 600) / V1 < T + (600 - x) / V2) puts("Yes"); 23 else puts("No"); 24 } 25 else if(V1 * 3 > V2) 26 { 27 double tmp = V2 / V1 * V2 / V1; 28 double a = tmp - 1, b = 1800, c = tmp * 90000 - 810000; 29 double x = (- b + sqrt(b * b - 4 * a * c)) / 2 / a; 30 if((sqrt((300 - x) * (300 - x) + 90000) + 900) / V1 < T + (300 + x) / V2) puts("Yes"); 31 else puts("No"); 32 } 33 else puts("No"); 34 } 35 return 0; 36 }
HDU 5478 Can you find it
嘿嘿嘿
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 typedef long long LL; 5 6 LL qpow(LL a, LL b, LL mod) 7 { 8 LL ret = 1LL; 9 while(b) 10 { 11 if(b & 1) ret = ret * a % mod; 12 a = a * a % mod; 13 b >>= 1; 14 } 15 return ret; 16 } 17 18 int main(void) 19 { 20 int kase = 0; 21 int C, k1, b1, k2; 22 while(~scanf("%d %d %d %d", &C, &k1, &b1, &k2)) 23 { 24 printf("Case #%d:\n", ++kase); 25 int ok = 0; 26 for(int a = 1; a < C; a++) 27 { 28 int b = C - qpow(a, k1 + b1, C); 29 if(qpow(a, k1, C) == qpow(b, k2, C)) 30 { 31 ok = 1; 32 printf("%d %d\n", a, b); 33 } 34 } 35 if(!ok) puts("-1"); 36 } 37 return 0; 38 }
7.14
HDU 5534 Partial Tree
高老师太神拉。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 int f[2222], dp[2222]; 6 7 int main(void) 8 { 9 int T; 10 scanf("%d", &T); 11 while(T--) 12 { 13 int n; 14 scanf("%d", &n); 15 for(int i = 1; i < n; i++) scanf("%d", f + i); 16 for(int i = 2; i < n; i++) 17 { 18 dp[i] = f[i] + (i - 2) * f[1]; 19 for(int j = 2; j <= i - j + 1; j++) 20 dp[i] = max(dp[i], dp[j] + dp[i-j+1]); 21 } 22 printf("%d\n", dp[n-1] + 2 * f[1]); 23 } 24 return 0; 25 }
HDU 5492 Find a path
The magic values are no greater than 30.
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int G[31][31], dp[31][31][1801]; 5 6 int main(void) 7 { 8 int T; 9 scanf("%d", &T); 10 for(int kase = 1; kase <= T; kase++) 11 { 12 int N, M; 13 scanf("%d %d", &N, &M); 14 for(int i = 1; i <= N; i++) 15 for(int j = 1; j <= M; j++) 16 scanf("%d", &G[i][j]); 17 18 for(int i = 0; i <= N; i++) 19 for(int j = 0; j <= M; j++) 20 for(int k = 0; k <= 1800; k++) 21 dp[i][j][k] = 1e9; 22 23 dp[1][1][G[1][1]] = 0; 24 for(int i = 1; i <= N; i++) 25 { 26 for(int j = 1; j <= M; j++) 27 { 28 if(i == 1 && j == 1) continue; 29 for(int k = 0; k <= 1800; k++) 30 { 31 if(dp[i-1][j][k] != 1e9) dp[i][j][k+G[i][j]] = min(dp[i][j][k+G[i][j]], ((dp[i-1][j][k] + k * k) / (i + j - 2) + G[i][j] * G[i][j]) * (i + j - 1) - (k + G[i][j]) * (k + G[i][j])); 32 if(dp[i][j-1][k] != 1e9) dp[i][j][k+G[i][j]] = min(dp[i][j][k+G[i][j]], ((dp[i][j-1][k] + k * k) / (i + j - 2) + G[i][j] * G[i][j]) * (i + j - 1) - (k + G[i][j]) * (k + G[i][j])); 33 } 34 } 35 } 36 37 int ans = 1e9; 38 for(int i = 0; i <= 1800; i++) ans = min(ans, dp[N][M][i]); 39 printf("Case #%d: %d\n", kase, ans); 40 41 } 42 return 0; 43 }