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 }
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 }
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 }
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 }
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 }