2014 ACM/ICPC--鞍山同步赛
2014-10-22 22:42:20
花了几个小时做了四道题。
B题大模拟...搞了很久,最后是把繁琐的STL全部去掉才过的TAT。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 typedef long long ll; 6 7 int T,n,sz,altop,alpos; 8 struct node{ 9 int p,w; 10 }no[10010]; 11 12 void Move(int pos){ 13 if(alpos && alpos <= pos){ 14 if(alpos == pos) alpos = 1; 15 else alpos++; 16 } 17 node tmp = no[pos]; 18 for(int i = pos; i > 1; --i) 19 no[i] = no[i - 1]; 20 no[1] = tmp; 21 } 22 23 int main(){ 24 int a; 25 char s[20]; 26 scanf("%d",&T); 27 while(T--){ 28 memset(no,0,sizeof(no)); 29 altop = alpos = sz = 0; 30 scanf("%d",&n); 31 for(int Case = 1; Case <= n; ++Case){ 32 printf("Operation #%d: ", Case); 33 scanf("%s",s); 34 if(s[0] == 'A'){ //Add 35 scanf("%d",&a); 36 int flag = 0; 37 for(int i = 1; i <= sz; ++i) if(no[i].p == a){ 38 flag = 1; break; 39 } 40 if(flag){ //已经存在 41 printf("same priority.\n"); 42 continue; 43 } 44 no[++sz].p = a; 45 no[sz].w = 0; 46 printf("success.\n"); 47 } 48 else if(s[0] == 'C' && s[1] == 'l'){ //Close 49 scanf("%d",&a); 50 int pos = 0; 51 for(int i = 1; i <= sz; ++i) if(no[i].p == a){ 52 pos = i; 53 break; 54 } 55 if(pos == 0){ //不存在 56 printf("invalid priority.\n"); 57 continue; 58 } 59 printf("close %d with %d.\n",no[pos].p,no[pos].w); 60 if(alpos > pos) --alpos; 61 for(int i = pos + 1; i <= sz; ++i) 62 no[i - 1] = no[i]; 63 --sz; 64 if(altop == a) altop = alpos = 0; 65 } 66 else if(s[0] == 'C' && s[1] == 'h' && s[2] == 'a'){ //Chat 67 scanf("%d",&a); 68 if(sz == 0){ 69 printf("empty.\n"); 70 continue; 71 } 72 if(altop) no[alpos].w += a; 73 else no[1].w += a; 74 printf("success.\n"); 75 } 76 else if(s[0] == 'R'){ //Rotate 77 scanf("%d",&a); 78 if(a < 1 || a > sz){ 79 printf("out of range.\n"); 80 continue; 81 } 82 Move(a); 83 printf("success.\n"); 84 } 85 else if(s[0] == 'P'){ //Prior 86 if(sz == 0){ 87 printf("empty.\n"); 88 continue; 89 } 90 int pos = 1; 91 for(int i = 1; i <= sz; ++i) if(no[i].p > no[pos].p) 92 pos = i; 93 Move(pos); 94 printf("success.\n"); 95 } 96 else if(s[0] == 'C' && s[1] == 'h' && s[2] == 'o'){ //Choose 97 scanf("%d",&a); 98 int pos = 0; 99 for(int i = 1; i <= sz; ++i) if(no[i].p == a){ 100 pos = i; 101 break; 102 } 103 if(pos == 0){ //不存在 104 printf("invalid priority.\n"); 105 continue; 106 } 107 Move(pos); 108 printf("success.\n"); 109 } 110 else if(s[0] == 'T'){ //Top 111 scanf("%d",&a); 112 int pos = 0; 113 for(int i = 1; i <= sz; ++i) if(no[i].p == a){ 114 pos = i; 115 break; 116 } 117 if(pos == 0){ //不存在 118 printf("invalid priority.\n"); 119 continue; 120 } 121 altop = a; 122 alpos = pos; 123 printf("success.\n"); 124 } 125 else{ //Untop 126 if(alpos == 0){ 127 printf("no such person.\n"); 128 continue; 129 } 130 altop = alpos = 0; 131 printf("success.\n"); 132 } 133 } 134 if(alpos && no[alpos].w) 135 printf("Bye %d: %d\n",altop,no[alpos].w); 136 for(int i = 1; i <= sz; ++i) if(no[i].w && no[i].p != altop) 137 printf("Bye %d: %d\n",no[i].p,no[i].w); 138 } 139 return 0; 140 }
C题是个容斥,请教了bin神,呼呼思路精巧。
做法:(1)首先用容斥原理找出对于每个数,n个数中与其不互质 / 互质的数的个数。具体方法是将这个数唯一素数分解,然后用Dfs算出分解出的素数能组成哪些数(如:60分解出:2,3,5,三个素数,然后他们能组合出6,10,15,30这些数,开一个计数数组cnt,cnt[2、3、5、6、10、15、30] + 1),这样做的目的等会在容斥中就能理解。
(2)对每个数容斥:将这个数分解素数,如15,能分解出3、5,那么与15不互质的数的个数就是:含因数3的数 + 含因数5的数 - 含因数3*5=15的数(因为15被算了两次),这样就能理解为什么(1)中这么处理了。(好吧,说的好乱,具体看代码吧)
1 /************************************************************************* 2 > File Name: 1003.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Wed 22 Oct 2014 02:03:15 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 27 int T; 28 int a[300010]; 29 int fac[100010]; 30 int f[100],cnt; 31 ll ans,n; 32 33 void Dfs(int p,int c,int val){ 34 if(p > cnt){ 35 if(c & 1) ans += fac[val] - 1; 36 else if(c > 0) ans -= fac[val] - 1; 37 return; 38 } 39 Dfs(p + 1,c,val); 40 Dfs(p + 1,c + 1,val * f[p]); 41 } 42 43 void Dfs1(int p,int c,int val){ 44 if(p > cnt){ 45 if(c > 1) fac[val]++; 46 return; 47 } 48 Dfs1(p + 1,c,val); 49 Dfs1(p + 1,c + 1,val * f[p]); 50 } 51 52 int main(){ 53 int v,tmp; 54 scanf("%d",&T); 55 while(T--){ 56 scanf("%I64d",&n); 57 memset(fac,0,sizeof(fac)); 58 for(int i = 1; i <= n; ++i){ 59 scanf("%d",a + i); 60 tmp = a[i]; 61 v = sqrt(1.0 * tmp); 62 cnt = 0; 63 for(int j = 2; j <= v; ++j) if(tmp % j == 0){ 64 f[++cnt] = j; 65 fac[j]++; 66 while(tmp % j == 0) tmp /= j; 67 } 68 if(tmp != 1){ 69 f[++cnt] = tmp; 70 fac[tmp]++; 71 } 72 Dfs1(1,0,1); 73 } 74 ll res = 0; 75 for(int i = 1; i <= n; ++i){ 76 cnt = 0; 77 tmp = a[i]; 78 v = sqrt(1.0 * tmp); 79 for(int j = 2; j <= v; ++j) if(tmp % j == 0){ 80 f[++cnt] = j; 81 while(tmp % j == 0) tmp /= j; 82 } 83 if(tmp != 1){ 84 f[++cnt] = tmp; 85 } 86 ans = 0; 87 Dfs(1,0,1); 88 res += ans * (n - 1 - ans); 89 } 90 printf("%I64d\n",n * (n - 1) * (n - 2) / (ll)6 - res / (ll)2); 91 } 92 return 0; 93 } 94
D题就是维护一个(n-k)的框,框内答案为 a1^2+a2^2+...+an-k^2 - (a1+a2+...+an-k)^2 / (n-k)
1 /************************************************************************* 2 > File Name: 1004.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Wed 22 Oct 2014 11:26:09 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 27 int T; 28 ll n,k,a[50010],sum[50010],sum2[50010]; 29 30 int main(){ 31 scanf("%d",&T); 32 while(T--){ 33 scanf("%I64d%I64d",&n,&k); 34 sum[0] = sum2[0] = 0; 35 for(int i = 1; i <= n; ++i){ 36 scanf("%I64d",&a[i]); 37 } 38 sort(a + 1,a + n + 1); 39 for(int i = 1; i <= n; ++i){ 40 sum[i] = sum[i - 1] + a[i]; 41 sum2[i] = sum2[i - 1] + a[i] * a[i]; 42 } 43 if(k == 0){ 44 printf("%.10f\n",1.0 * sum2[n] - sum[n] * sum[n] / (1.0 * n)); 45 continue; 46 } 47 if(n == k){ 48 printf("0\n"); 49 continue; 50 } 51 ll ans = (n - k) * sum2[n - k] - sum[n - k] * sum[n - k]; 52 for(int i = n - k + 1; i <= n; ++i){ 53 ans = min(ans,(n - k) * (sum2[i] - sum2[i - n + k]) - 54 (sum[i] - sum[i - n + k]) * (sum[i] - sum[i - n + k])); 55 } 56 printf("%.10f\n",(double)ans / (1.0 * n - k)); 57 } 58 return 0; 59 }
E题是个比较基础的DP,dp[i][j]表示长度为i,且第i位为j的最优解。dp[i][j] = max(dp[i - 1][k] + g[k][j])
1 /************************************************************************* 2 > File Name: 1005.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Wed 22 Oct 2014 03:07:01 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 27 int T; 28 int n,m; 29 int g[55][55]; 30 int a[105]; 31 int dp[105][55]; 32 33 int main(){ 34 scanf("%d",&T); 35 while(T--){ 36 scanf("%d%d",&n,&m); 37 for(int i = 1; i <= m; ++i) 38 for(int j = 1; j <= m; ++j) 39 scanf("%d",&g[i][j]); 40 for(int i = 1; i <= n; ++i) 41 scanf("%d",a + i); 42 for(int i = 1; i <= n; ++i) 43 for(int j = 1; j <= m; ++j) 44 dp[i][j] = -INF; 45 if(a[1] == -1) 46 for(int j = 1; j <= m; ++j) 47 dp[1][j] = 0; 48 else 49 dp[1][a[1]] = 0; 50 int ans = 0; 51 for(int i = 2; i <= n; ++i){ 52 if(a[i] != -1){ 53 for(int k = 1; k <= m; ++k){ 54 dp[i][a[i]] = max(dp[i][a[i]],dp[i - 1][k] + g[k][a[i]]); 55 } 56 ans = max(ans,dp[i][a[i]]); 57 } 58 else{ 59 for(int j = 1; j <= m; ++j){ 60 for(int k = 1; k <= m; ++k){ 61 dp[i][j] = max(dp[i][j],dp[i - 1][k] + g[k][j]); 62 } 63 ans = max(ans,dp[i][j]); 64 } 65 } 66 } 67 printf("%d\n",ans); 68 } 69 return 0; 70 }

浙公网安备 33010602011771号