第四周 7.31-8.6
啦啦啦旅游拉。
7.31
补套BC。
HDU 5776 sum
离散数学课本题!小学生抽屉原理!
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 const int maxn = 1e5 + 10; 5 int x[maxn]; 6 7 int main(void) 8 { 9 int T; 10 scanf("%d", &T); 11 while(T--) 12 { 13 int n, m; 14 scanf("%d %d", &n, &m); 15 for(int i = 1; i <= n; i++) scanf("%d", x + i); 16 if(n > m) puts("YES"); 17 else 18 { 19 int ok = 0; 20 for(int i = 2; i <= n; i++) x[i] += x[i-1]; 21 for(int i = 1; i <= n; i++) 22 for(int j = 0; j < i; j++) 23 if((x[i]-x[j]) % m == 0) {ok = 1;break;} 24 puts(ok ? "YES" : "NO"); 25 } 26 } 27 return 0; 28 }
HDU 5777 domino
答案最少也有n,要推倒旁边一个,高度就要加上距离。贪心的去掉最大的几个就好了。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 1e5 + 10; 6 typedef long long LL; 7 int d[maxn]; 8 9 int main(void) 10 { 11 int T; 12 scanf("%d", &T); 13 while(T--) 14 { 15 int n, k; 16 scanf("%d %d", &n, &k); 17 for(int i = 1; i < n; i++) scanf("%d", d + i); 18 if(k >= n) printf("%d\n", n); 19 else 20 { 21 sort(d + 1, d + n); 22 LL ans = n; 23 for(int i = 1; i <= n - k; i++) ans = ans + d[i]; 24 printf("%I64d\n", ans); 25 } 26 } 27 return 0; 28 }
HDU 5778 abs
素数定理,1e9之内素数间距离最大也就两百多。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 1e5 + 10; 6 typedef long long LL; 7 int d[maxn]; 8 9 int main(void) 10 { 11 int T; 12 scanf("%d", &T); 13 while(T--) 14 { 15 int n, k; 16 scanf("%d %d", &n, &k); 17 for(int i = 1; i < n; i++) scanf("%d", d + i); 18 if(k >= n) printf("%d\n", n); 19 else 20 { 21 sort(d + 1, d + n); 22 LL ans = n; 23 for(int i = 1; i <= n - k; i++) ans = ans + d[i]; 24 printf("%I64d\n", ans); 25 } 26 } 27 return 0; 28 }
HDU 5779 Tower Defence
先按题解那样搞。大概还要预处理一些2的阶乘、组合数、(2^k-1)^j之类的。
然后g[n][k]表示n个点,最短路为k的方案。
求个前缀和,再加上最短路无穷的情况。
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 typedef long long LL; 5 const LL mod = 1e9 + 7; 6 LL f[66][66][66], g[66][66]; 7 LL p[6666], c[66][66], e[66][66]; 8 9 int main(void) 10 { 11 p[0] = 1; 12 for(int i = 1; i <= 3600; i++) p[i] = p[i-1] * 2 % mod; 13 14 for(int k = 1; k <= 60; k++) 15 { 16 e[k][0] = 1; 17 for(int j = 1; j <= 60; j++) 18 e[k][j] = e[k][j-1] * (p[k] - 1 + mod) % mod; 19 } 20 21 for(int i = 0; i <= 60; i++) c[i][0] = c[i][i] = 1; 22 for(int i = 2; i <= 60; i++) 23 for(int j = 1; j < i; j++) 24 c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mod; 25 26 27 f[1][0][1] = 1; 28 for(int i = 2; i <= 60; i++) 29 for(int d = 1; d <= i - 1; d++) 30 for(int j = 1; j <= i - d; j++) 31 { 32 for(int k = 1; k <= i - j - d + 1; k++) 33 f[i][d][j] = (f[i][d][j] + f[i-j][d-1][k] * e[k][j]) % mod; 34 f[i][d][j] = f[i][d][j] * p[j*(j-1)/2] % mod; 35 f[i][d][j] = f[i][d][j] * c[i-1][j] % mod; 36 } 37 38 for(int n = 1; n <= 60; n++) 39 for(int k = 1; k < n; k++) 40 { 41 for(int i = k + 1; i <= n; i++) 42 for(int j = 1; j <= i - k; j++) 43 g[n][k] = (g[n][k] + f[i][k][j] * c[n-1][i-1] % mod * p[(n-i)*(n-i-1)/2]) % mod; 44 } 45 46 47 for(int n = 1; n <= 60; n++) 48 { 49 g[n][0] = p[(n-1)*(n-2)/2]; 50 for(int k = 1; k <= 60; k++) 51 g[n][k] = (g[n][k] + g[n][k-1]) % mod; 52 } 53 int T; 54 scanf("%d", &T); 55 while(T--) 56 { 57 int n, k; 58 scanf("%d %d", &n, &k); 59 printf("%I64d\n", g[n][k-1]); 60 } 61 62 return 0; 63 }
HDU 5780 gcd
大概就是“古老的小技巧”的应用了。
不过学习了线性的逆元……
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 typedef long long LL; 6 const LL mod = 1e9 + 7; 7 const int maxn = 1e6 + 10; 8 9 int phi[maxn]; 10 void get_phi() 11 { 12 memset(phi, 0, sizeof(phi)); 13 phi[1] = 1; 14 for(int i = 2; i < maxn; i++) 15 { 16 if(phi[i]) continue; 17 for(int j = i; j < maxn; j += i) 18 { 19 if(!phi[j]) phi[j] = j; 20 phi[j] = phi[j] / i * (i - 1); 21 } 22 } 23 } 24 25 LL qpow(LL a, LL b) 26 { 27 LL ret = 1LL; 28 while(b) 29 { 30 if(b & 1) ret = ret * a % mod; 31 a = a * a % mod; 32 b >>= 1; 33 } 34 return ret; 35 } 36 37 LL sum[maxn], inv[maxn], p[maxn]; 38 int main(void) 39 { 40 get_phi(); 41 for(int i = 1; i < maxn; i++) sum[i] = (sum[i-1] + phi[i]) % mod; 42 43 inv[1] = 1; 44 for(int i = 2; i < maxn; i++) inv[i] = (mod - (mod / i) * inv[mod%i] % mod) % mod; 45 46 int T; 47 scanf("%d", &T); 48 while(T--) 49 { 50 int x, n; 51 scanf("%d %d", &x, &n); 52 53 if(x == 1) {puts("0"); continue;} 54 55 LL ans = 0; 56 for(int i = 1; i <= n; i++) 57 { 58 int j = n / (n / i); 59 LL sd = (sum[n/i] + sum[n/i] + mod - 1) % mod; 60 LL tmp = (qpow(x, i) * (qpow(x, j - i + 1) - 1 + mod) % mod * inv[x-1] - j + i - 1 + mod) % mod; 61 ans = (ans + sd * tmp) % mod; 62 i = j; 63 } 64 65 printf("%I64d\n", ans); 66 67 } 68 return 0; 69 }