2014 ACM-ICPC Vietnam National Second Round

2015-03-15 00:15:48

下午打的gym,“chinese nue round”... 比赛A了4个数学 / 水题(A,B,D,I)... 赛后把C题补掉了。

 

A:暴力。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=1;i<=(n);++i)
17 #define REV(i,n) for(int i=(n);i>=1;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 int N,W,T;
28 int v[110];
29 
30 int main(){
31     scanf("%d",&T);
32     REP(tt,T){
33         int ans = 0;
34         scanf("%d%d",&N,&W);
35         REP(i,N) scanf("%d",v + i);
36         REP(i,N){
37             int tmax = 0;
38             FOR(j,i + 1,N) tmax = max(tmax,v[j]);
39             ans = max(ans,W / v[i] * (tmax - v[i]));
40         }
41         printf("%d\n",ans);
42     }
43     return 0;
44 }
View Code

 

B:一个n/1 + n/2 + n/3 + ... + n/n的序列求和,发现数越小,该数的个数越多。那么我们单独处理出分母为1~sqrt(n),然后枚举n/k的答案为1,2,3... 的个数。

  n/k为1的个数为n - n/2;

  n/k为2的个数为n/2-n/3;

  ...

  n/k为m的个数为n/m - n/(m+1)

  ...

  那么我们算完前sqrt(n)后,倒过来从n/k=1,2,3..开始枚举。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=1;i<=(n);++i)
17 #define REV(i,n) for(int i=(n);i>=1;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 const ll mod = 1e6;
27 
28 int T;
29 ll n;
30 
31 int main(){
32     cin >> T;
33     REP(tt,T){
34         cin >> n;
35         ll k = sqrt(1.0 * n);
36         ll sum = 0;
37         for(int i = 1; i <= k; ++i)
38             sum = (sum + n / i) % mod;
39         k = n - k;
40         ll tmp,cnt = 1;
41         while(k){
42             tmp = n / cnt - n / (cnt + 1);
43             tmp = min(k,tmp);
44             sum = (sum + cnt * tmp) % mod;
45             k -= tmp;
46             ++cnt;
47         }
48         cout << sum << endl;
49     }
50     return 0;
51 }
View Code

 

C:引用题解,首先容易发现把W/1000,然后再把1000,2000,3000,5000看成:1,2,3,5。

   处理出每一位1~9,用1,2,3,5组合相加来表示,然后逐位考虑。

   这样会有一个问题,那就是11可由5+5+1和5+3+3,两种方法组成。

   可以这样解决:设最大的面值是t=5*10^c,先将 W 减去 W / t * t

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=1;i<=(n);++i)
17 #define REV(i,n) for(int i=(n);i>=1;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 int T,c;
28 ll W,v[20][20];
29 ll num[20],di[20];
30 
31 ll Q_pow(ll x,ll y){
32     ll res = 1;
33     while(y){
34         if(y & 1) res = res * x;
35         x = x * x;
36         y >>= 1;
37     }
38     return res;
39 }
40 
41 int main(){
42     num[1] = num[2] = num[3] = num[5] = 1;
43     num[4] = num[6] = num[11] = 2;
44     num[7] = num[8] = num[10] = 1;
45     num[9] = 3;
46     di[1] = di[2] = di[3] = di[5] = 1;
47     di[4] = di[6] = di[7] = di[8] = di[10] = 2;
48     di[9] = di[11] = 3;
49     scanf("%d",&T);
50     REP(tt,T){
51         cin >> W >> c;
52         for(int i = 1; i <= 9; ++i) v[0][i] = i;
53         v[0][10] = 11,v[0][11] = 10;
54         for(int i = 1; i <= c; ++i)
55             for(int j = 1; j <= 11; ++j)
56                 v[i][j] = v[i - 1][j] * 10LL;
57         if(W == 0 || W % 1000){
58             printf("0\n");
59             continue;
60         }
61         W /= 1000LL;
62         ll m = W >= v[c][5] ? (W - v[c][5]) / v[c][5] : 0;
63         ll ans = m,cnt = 1;
64         W -= m * v[c][5];
65         for(int i = c; i >= 0; --i){
66             for(int j = 9; j >= 1; --j){
67                 if(W / v[i][j]){
68                     ll now = W / v[i][j];
69                     W -= now * v[i][j];
70                     ans += now * di[j];
71                     cnt *= Q_pow(num[j],now);
72                 }
73             }
74         }
75         cout << ans << " " << cnt << endl;
76     }
77     return 0;
78 }
View Code

 

D:打表发现... N%100的循环节长度为20,而且从第二个循环节开始稳定:... 1~20个和21~40个数可能不一样,但21~40与41~60... 均形成循环节。

   然后就是把K缩小就行。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=1;i<=(n);++i)
17 #define REV(i,n) for(int i=(n);i>=1;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 int T;
28 ll N,K;
29 int vis[110];
30 
31 int main(){
32     scanf("%d",&T);
33     REP(tt,T){
34         cin >> N >> K;
35         if(K <= 40){
36             for(int i = 1; i <= K; ++i)    N = N + N % 100;
37         }
38         else{
39             for(int i = 1; i <= 20; ++i) N = N + N % 100;
40             ll sum = 0;
41             for(int i = 1; i <= 20; ++i){
42                 sum += N % 100;
43                 N = N + N % 100;
44             }
45             K -= 40;
46             N = N + K / 20 * sum;
47             K -= K / 20 * 20;
48             for(int i = 1; i <= K; ++i) N = N + N % 100;
49         }
50         cout << N << endl;
51     }
52     return 0;
53 }
View Code

 

I:预处理出每个点往8个方向走的最长路径长度,8个方向:上左、上右、右上、右下..... 

  然后就是枚举每个点为着陆点。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=1;i<=(n);++i)
17 #define REV(i,n) for(int i=(n);i>=1;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 int T,N,M;
28 char g[1010][1010];
29 int sum[1010][1010][8];
30 
31 int main(){
32     scanf("%d",&T);
33     REP(tt,T){
34         MEM(sum,0);
35         scanf("%d%d",&M,&N);
36         REP(i,M) scanf("%s",g[i] + 1);
37         REP(i,M) REP(j,N) if(g[i][j] == '1'){
38             sum[i][j][0] = sum[i - 1][j][7] + 1;
39             sum[i][j][7] = sum[i][j - 1][0] + 1;
40         }
41         REP(i,M) REV(j,N) if(g[i][j] == '1'){
42             sum[i][j][1] = sum[i - 1][j][2] + 1;
43             sum[i][j][2] = sum[i][j + 1][1] + 1;
44         }
45         REV(i,M) REP(j,N) if(g[i][j] == '1'){
46             sum[i][j][5] = sum[i + 1][j][6] + 1;
47             sum[i][j][6] = sum[i][j - 1][5] + 1;
48         }
49         REV(i,M) REV(j,N) if(g[i][j] == '1'){
50             sum[i][j][3] = sum[i][j + 1][4] + 1;
51             sum[i][j][4] = sum[i + 1][j][3] + 1;
52         }
53         int ans = 0;
54         REP(i,M) REP(j,N){
55 #define tmp sum[i][j]
56             int cur = tmp[1] + tmp[3] + tmp[5] + tmp[7] - 3;
57             ans = max(ans,cur);
58 #undef tmp
59         }
60         printf("%d\n",ans);
61     }
62     return 0;
63 }
View Code

 

posted @ 2015-03-15 00:44  Naturain  阅读(177)  评论(0编辑  收藏  举报