AtCoder Beginner Contest 258 Solution更好的阅读体验戳此进入题面链接题面 Luogu 链接abcd 跳了[ABC258E] Packing Potatoes题面SolutionCode[ABC258F] Main Street题面SolutionCode[ABC258G] Triangle题面SolutionCode[ABC258Ex] Odd Steps题面SolutionCodeUPD
给定序列
一道细节不少的找规律题。
首先不难发现,对于这个箱子,当你确定了从哪里开始装后,其最远能装到的位置也就确定了。我们考虑如何确定这个东西,不难想到做个前缀和然后二分,找到对应点开始的最长能取的长度,细节较多,如需要注意若长度仅为一初值需要判断。因为可能转回去所以可以将序列复制一份然后在这上面跑即可。
此时仍需要注意
复杂度卡在预处理上,最终复杂度
xxxxxxxxxx
911
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int N, Q, X;
26int W[410000];
27ll sum[410000];
28int nxt[210000];
29ll siz[210000];
30ll lftans(0);
31bitset < 210000 > vis;
32int pos[210000];
33int mark[210000];
34int pre[210000];
35
36int main(){
37 // freopen("in.txt", "r", stdin);
38 N = read(), Q = read(), X = read();
39 for(int i = 1; i <= N; ++i)sum[i] = sum[i - 1] + (W[i] = read());
40 copy(W + 1, W + N + 1, W + N + 1);
41 for(int i = N + 1; i <= N << 1; ++i)sum[i] = sum[i - 1] + W[i];
42 ll tot = sum[N];
43 lftans += ll(X / tot) * N;
44 X %= tot;
45 if(!X)lftans -= N, X += tot;
46 for(int i = 1; i <= N; ++i){
47 int l = i, r = N << 1, ans(i - 1);
48 while(l <= r){
49 int mid = (l + r) >> 1;
50 if(sum[mid] - sum[i - 1] < X)ans = mid, l = mid + 1;
51 else r = mid - 1;
52 }nxt[i] = ans += 2;
53 siz[i] = lftans + (nxt[i] - i);
54 if(nxt[i] > N)nxt[i] -= N;
55 }
56 queue < int > path;
57 int cur = 1, len = 0;
58 while(!vis[cur]){
59 path.push(cur);
60 vis[cur] = true;
61 mark[++len] = cur;
62 cur = nxt[cur];
63 }int cnt(0);
64 while(path.front() != cur)pre[++cnt] = path.front(), path.pop();
65 len = 0;
66 while(!path.empty())pos[++len] = path.front(), path.pop();
67 pos[0] = pos[len];
68 while(Q--){
69 ll K = read < ll >();
70 if(K <= cnt)printf("%lld\n", siz[pre[K]]);
71 else printf("%lld\n", siz[pos[(K - cnt) % len]]);
72 }
73 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
74 return 0;
75}
76
77template < typename T >
78inline T read(void){
79 T ret(0);
80 int flag(1);
81 char c = getchar();
82 while(c != '-' && !isdigit(c))c = getchar();
83 if(c == '-')flag = -1, c = getchar();
84 while(isdigit(c)){
85 ret *= 10;
86 ret += int(c - '0');
87 c = getchar();
88 }
89 ret *= flag;
90 return ret;
91}
你要在平面直角坐标系中行走,每一步可以上下左右四个方向任意移动
显然可以选择直接走,或者走到起点附近的某个快速通道即终点附近的某个快速通道,共有
xxxxxxxxxx
1791
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int B, K;
26int Sx, Sy, Tx, Ty;
27
28int main(){
29 int T = read();
30 while(T--){
31 B = read(), K = read();
32 Sx = read(), Sy = read(), Tx = read(), Ty = read();
33 pair < int, int > S[10] = {
34 {0, 0},
35 {Sx / B * B, Sy},
36 {Sx, int(ceil((double)Sy / B)) * B},
37 {int(ceil((double)Sx / B)) * B, Sy},
38 {Sx, Sy / B * B}
39 };
40 pair < int, int > T[10] = {
41 {0, 0},
42 {Tx / B * B, Ty},
43 {Tx, int(ceil((double)Ty / B)) * B},
44 {int(ceil((double)Tx / B)) * B, Ty},
45 {Tx, Ty / B * B}
46 };
47 ll ans = ll(abs(Sx - Tx) + abs(Sy - Ty)) * K;
48 for(int s = 1; s <= 4; ++s)
49 for(int t = 1; t <= 4; ++t)
50 ans = min(
51 ans,
52 abs(S[s].first - T[t].first) + abs(S[s].second - T[t].second) +
53 (
54 (ll)(abs(S[s].first - Sx) + abs(S[s].second - Sy)) * K +
55 (ll)(abs(T[t].first - Tx) + abs(T[t].second - Ty)) * K
56 )
57 );
58 printf("%lld\n", ans);
59 }
60
61 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
62 return 0;
63}
64
65template < typename T >
66inline T read(void){
67 T ret(0);
68 int flag(1);
69 char c = getchar();
70 while(c != '-' && !isdigit(c))c = getchar();
71 if(c == '-')flag = -1, c = getchar();
72 while(isdigit(c)){
73 ret *= 10;
74 ret += int(c - '0');
75 c = getchar();
76 }
77 ret *= flag;
78 return ret;
79}
给你一个简单的无向图,其中有
求三角形
枚举 bitset
优化,最终复杂度
x
1
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int N;
26ll ans(0);
27bitset < 3100 > G[3100];
28
29int main(){
30 N = read();
31 for(int i = 1; i <= N; ++i)for(int j = 1; j <= N; ++j){
32 char c = getchar(); while(!isdigit(c))c = getchar();
33 G[i][j] = c == '1' && j > i ? true : false;
34 }
35 for(int i = 1; i <= N; ++i)for(int j = i + 1; j <= N; ++j)
36 if(G[i][j])ans += (G[i] & G[j]).count();
37 printf("%lld\n", ans);
38 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
39 return 0;
40}
41
42template < typename T >
43inline T read(void){
44 T ret(0);
45 int flag(1);
46 char c = getchar();
47 while(c != '-' && !isdigit(c))c = getchar();
48 if(c == '-')flag = -1, c = getchar();
49 while(isdigit(c)){
50 ret *= 10;
51 ret += int(c - '0');
52 c = getchar();
53 }
54 ret *= flag;
55 return ret;
56}
给定
答案对
首先不考虑最后一个限制,则不难想到 DP,即设
然后发现转移为
边界为
然后复杂度是
矩阵快速幂优化即可。
然后对于第三个限制,我们只需要在维护的时候分段维护即可,每次维护到对应的
最终复杂度
xxxxxxxxxx
1821
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22
23
24template < typename T = int >
25inline T read(void);
26
27int N;
28ll S;
29ll P[110000];
30
31class Matrix3{
32private:
33public:
34 ll v[3][3];
35 Matrix3(ll v11 = 0, ll v12 = 0, ll v13 = 0, ll v21 = 0, ll v22 = 0, ll v23 = 0, ll v31 = 0, ll v32 = 0, ll v33 = 0){
36 v[0][0] = v11, v[0][1] = v12, v[0][2] = v13,
37 v[1][0] = v21, v[1][1] = v22, v[1][2] = v23,
38 v[2][0] = v31, v[2][1] = v32, v[2][2] = v33;
39 }
40 friend const Matrix3 operator * (const Matrix3 &a, const Matrix3 &b){
41 Matrix3 ret;
42 for(int i = 0; i <= 2; ++i)for(int j = 0; j <= 2; ++j)for(int k = 0; k <= 2; ++k)
43 (ret.v[i][j] += a.v[i][k] * b.v[k][j] % MOD) %= MOD;
44 return ret;
45 }
46 friend const Matrix3 operator ^ (const Matrix3 &a, ll b){
47 Matrix3 ret(1, 0, 0, 0, 1, 0, 0, 0, 1), mul(a);
48 while(b){
49 if(b & 1)ret = ret * mul;
50 b >>= 1;
51 mul = mul * mul;
52 }return ret;
53 }
54};
55
56int main(){
57 N = read(), S = read < ll >();
58 for(int i = 1; i <= N; ++i)P[i] = read < ll >();
59 Matrix3 base(1, 1, 0, 0, 0, 1, 1, 1, 0);
60 Matrix3 ans(1, 0, 0);
61 for(int i = 1; i <= N; ++i)ans = ans * (base ^ (P[i] - P[i - 1])), ans.v[0][0] = 0;
62 ans = ans * (base ^ (S - P[N]));
63 printf("%lld\n", ans.v[0][0]);
64 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
65 return 0;
66}
67
68template < typename T >
69inline T read(void){
70 T ret(0);
71 int flag(1);
72 char c = getchar();
73 while(c != '-' && !isdigit(c))c = getchar();
74 if(c == '-')flag = -1, c = getchar();
75 while(isdigit(c)){
76 ret *= 10;
77 ret += int(c - '0');
78 c = getchar();
79 }
80 ret *= flag;
81 return ret;
82}
update-2022_12_17 初稿