AtCoder Beginner Contest 251 Solution更好的阅读体验戳此进入题面链接题面 Luogu 链接老样子abc太水了就跳了[ABC251D] At Most 3 (Contestant ver.)题面SolutionCode[ABC251E] Takahashi and Animals题面SolutionCode[ABC251F] Two Spanning Trees题面SolutionCodeG 是计算几何,暂时跳了,以后有机会再回来做[ABC251Ex] Fill Triangle题面SolutionCodeUPD
给你整数
显然按照十进制拆分成三组即可,即
xxxxxxxxxx
471
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 main(){
26 printf("297\n");
27 for(int i = 1; i <= 99; ++i)printf("%d %d %d ", i, i * 100, i * 10000);
28 printf("\n");
29 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
30 return 0;
31}
32
33template < typename T >
34inline T read(void){
35 T ret(0);
36 int flag(1);
37 char c = getchar();
38 while(c != '-' && !isdigit(c))c = getchar();
39 if(c == '-')flag = -1, c = getchar();
40 while(isdigit(c)){
41 ret *= 10;
42 ret += int(c - '0');
43 c = getchar();
44 }
45 ret *= flag;
46 return ret;
47}
有
输出喂食所有动物需要的最小花费。
DP 显然,令
xxxxxxxxxx
631
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;
26int a[310000];
27ll dp[310000][2];
28
29int main(){
30 N = read();
31 for(int i = 1; i <= N; ++i)a[i] = read();
32 memset(dp, 0x3f, sizeof dp);
33 dp[1][1] = a[1];
34 for(int i = 2; i <= N; ++i)
35 dp[i][0] = dp[i - 1][1],
36 dp[i][1] = min(dp[i - 1][1], dp[i - 1][0]) + a[i];
37 // for(int i = 1; i <= N; ++i)printf("%d: 0 = %lld, 1 = %lld\n", i, dp[i][0], dp[i][1]);
38 ll ans = min(dp[N][1], dp[N][0]);
39 dp[1][0] = 0;
40 for(int i = 2; i <= N; ++i)
41 dp[i][0] = dp[i - 1][1],
42 dp[i][1] = min(dp[i - 1][1], dp[i - 1][0]) + a[i];
43 ans = min(ans, dp[N][1]);
44 printf("%lld\n", ans);
45 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
46 return 0;
47}
48
49template < typename T >
50inline T read(void){
51 T ret(0);
52 int flag(1);
53 char c = getchar();
54 while(c != '-' && !isdigit(c))c = getchar();
55 if(c == '-')flag = -1, c = getchar();
56 while(isdigit(c)){
57 ret *= 10;
58 ret += int(c - '0');
59 c = getchar();
60 }
61 ret *= flag;
62 return ret;
63}
给定无向连通简单图,求其两个以
前者对图 DFS,后者对图 BFS,证明显然。
xxxxxxxxxx
831
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
25struct Edge{
26 Edge* nxt;
27 int to;
28 OPNEW;
29}ed[410000];
30ROPNEW(ed);
31Edge* head[410000];
32
33int N, M;
34bool vis[210000];
35
36void dfs(int p = 1){
37 vis[p] = true;
38 for(auto i = head[p]; i; i = i->nxt){
39 if(vis[SON])continue;
40 printf("%d %d\n", p, SON);
41 dfs(SON);
42 }
43}
44void bfs(void){
45 memset(vis, false, sizeof vis);
46 queue < int > cur;
47 cur.push(1), vis[1] = true;
48 while(!cur.empty()){
49 int tp = cur.front(); cur.pop();
50 for(auto i = head[tp]; i; i = i->nxt){
51 if(vis[SON])continue;
52 printf("%d %d\n", tp, SON);
53 vis[SON] = true, cur.push(SON);
54 }
55 }
56}
57
58int main(){
59 N = read(), M = read();
60 for(int i = 1; i <= M; ++i){
61 int s = read(), t = read();
62 head[s] = new Edge{head[s], t};
63 head[t] = new Edge{head[t], s};
64 }dfs(), bfs();
65 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
66 return 0;
67}
68
69template < typename T >
70inline T read(void){
71 T ret(0);
72 int flag(1);
73 char c = getchar();
74 while(c != '-' && !isdigit(c))c = getchar();
75 if(c == '-')flag = -1, c = getchar();
76 while(isdigit(c)){
77 ret *= 10;
78 ret += int(c - '0');
79 c = getchar();
80 }
81 ret *= flag;
82 return ret;
83}
存在序列
首先可以尝试随意给定一个序列
不难发现这玩意每一项实际上就是二项式系数,或者说杨辉三角。并且还能发现,对于每一行的元素,它们的系数均相同,不同的只是将下标整体向右平移了一位。
此时我们便可以根据这个性质,求出对于第
显然我们想要算出
显然序列
观察发现,这个东西平移之后,对于大多数的
具体地当我们移动询问区间的时候,遍历所有段,如果某一段的右端点在当前区间内,那么显然指向这一段的组合数会移动到下一段中,所以需要减掉前面的加上现在的。注意移动这步实际上是
于是现在的问题就仅剩如何求
首先还是考虑之前的思路,一定会有很多段的相同的
所以这个东西显然需要快速处理一段组合数,可以考虑做一个组合数的前缀和,这样即可
于是现在问题再次转化为如何快速求这种形式的组合数前缀和,可以参考该题:LG-P4345 [SHOI2015]超能粒子炮·改。
具体地,对于求
然后发现对于前面的
然后继续转化:
此时对比我们之前设的
然后我们只要随便与处理一下
考虑这个东西的复杂度,用主定理推导一下即可:
至此我们就终于完成了这道题。
xxxxxxxxxx
1151
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//7^6
24
25template < typename T = int >
26inline T read(void);
27
28int f[10][10];
29int N, M, K;
30int origin(0);
31int sumf[210];
32int lucas_div[SPL + 10], lucas_mod[SPL + 10];
33struct Blk{int l, r; int val;} blk[210];
34
35int qpow(int a, int b){
36 int ret(1), mul(a);
37 while(b){
38 if(b & 1)ret = ret * mul % MOD;
39 b >>= 1;
40 mul = mul * mul % MOD;
41 }return ret;
42}
43int fact[10], inv[10];
44void Init(void){
45 fact[0] = 1;
46 for(int i = 1; i < MOD; ++i)fact[i] = fact[i - 1] * i % MOD;
47 inv[MOD - 1] = qpow(fact[MOD - 1], MOD - 2);
48 for(int i = MOD - 2; i >= 0; --i)inv[i] = inv[i + 1] * (i + 1) % MOD;
49}
50int GetC(int n, int m){
51 if(n < m)return 0;
52 return fact[n] * inv[m] % MOD * inv[n - m] % MOD;
53}
54int Lucas(ll n, ll m){
55 if(n < MOD && m < MOD)return GetC(n, m);
56 return Lucas(n / MOD, m / MOD) * GetC(n % MOD, m % MOD) % MOD;
57}
58int O1Lucas(ll m){
59 return (lucas_div[m / SPL] * lucas_mod[m % SPL]) % MOD;
60}
61void InitF(void){
62 for(int i = 0; i <= MOD - 1; ++i)f[i][0] = f[0][i] = 1;
63 for(int i = 1; i <= MOD - 1; ++i)
64 for(int j = 1; j <= MOD - 1; ++j)
65 f[i][j] = (f[i][j - 1] + Lucas(i, j)) % MOD;
66}
67int F(ll n, ll k){
68 if(n < 0 || k < 0)return 0;
69 if(n < MOD && k < MOD)return f[n][k];
70 return (f[n % MOD][MOD - 1] * F(n / MOD, k / MOD - 1) % MOD + Lucas(n / MOD, k / MOD) * f[n % MOD][k % MOD] % MOD) % MOD;
71}
72
73int main(){
74 Init(), InitF();
75 N = read(), M = read(), K = read();
76 for(int i = 0; i <= SPL; ++i)lucas_div[i] = Lucas((N - K) / SPL, i), lucas_mod[i] = Lucas((N - K) % SPL, i);
77 int curl(1);
78 for(int i = 1; i <= M; ++i)blk[i].val = read(), blk[i].l = curl, blk[i - 1].r = blk[i].l - 1, curl += read();
79 blk[M].r = N; int lim = N - K + 1;
80 for(int i = 1; i <= M; ++i)
81 sumf[i] = (F(N - K, blk[i].r - 1) - F(N - K, blk[i].l - 2) + MOD) % MOD;
82 for(int i = 1; i <= M; ++i){
83 int l = blk[i].l, r = blk[i].r;
84 if(l > lim)break;
85 if(r <= lim)(origin += sumf[i] * blk[i].val % MOD) %= MOD;
86 else (origin += (F(N - K, lim - 1) - F(N - K, l - 2) + MOD) % MOD * blk[i].val % MOD) %= MOD;
87 }printf("%d ", origin);
88 int cl = 1, cr = lim;
89 for(int i = 2; i <= K; ++i){
90 for(int m = 1; m <= M; ++m){
91 int r = blk[m].r;
92 if(cl <= r && r <= cr)
93 origin = (origin - O1Lucas(r - cl) * blk[m].val % MOD + O1Lucas(r - cl) * blk[m + 1].val % MOD + MOD) % MOD;
94 }++cl, ++cr;
95 printf("%d ", origin);
96 }printf("\n");
97 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
98 return 0;
99}
100
101template < typename T >
102inline T read(void){
103 T ret(0);
104 int flag(1);
105 char c = getchar();
106 while(c != '-' && !isdigit(c))c = getchar();
107 if(c == '-')flag = -1, c = getchar();
108 while(isdigit(c)){
109 ret *= 10;
110 ret += int(c - '0');
111 c = getchar();
112 }
113 ret *= flag;
114 return ret;
115}
update-2022_12_02 初稿