2024.2.20 初三集训模拟测试2
和 DZ,lxyt 一起和初三考的一个模拟赛,不知道为啥让考,而且又是考试前头一天晚上告诉我们的(关键还是晚上下了课才告诉我们的)。
考的也还行,只不过
考试排名(三个难兄难弟)

T1 小P的2048
虽然你很强,但赢的人只会是我。
本身
按照题意模拟即可。
交给我吧!这次绝不搞砸。
#include <bits/stdc++.h> #define N 10 #define int long long using namespace std; int n,m,a[N][N],b[N][N],num,ans; queue < int > q; void Input(){ int x,y,v,xx,yy,vv;scanf("%lld%lld",&n,&m); scanf("%lld%lld%lld%lld%lld%lld",&x,&y,&v,&xx,&yy,&vv); a[x][y] = v,a[xx][yy] = vv; } void work_UP(int K,int V){ memset(b,0,sizeof(b)); for(int j = 1;j <= n;j ++){ for(int i = 1;i <= n;i ++) if(a[i][j] != 0) q.push(a[i][j]); int tot = 0;while(!q.empty()){ int x = q.front();q.pop(); if(q.empty() or x != q.front()) b[++tot][j] = x; else b[++tot][j] = x * 2,q.pop(),num += x * 2; } } } void work_DOWN(int K,int V){ memset(b,0,sizeof(b)); for(int j = 1;j <= n;j ++){ for(int i = n;i >= 1;i --) if(a[i][j] != 0) q.push(a[i][j]); int tot = n + 1;while(!q.empty()){ int x = q.front();q.pop(); if(q.empty() or x != q.front()) b[--tot][j] = x; else b[--tot][j] = x * 2,q.pop(),num += x * 2; } } } void work_LEFT(int K,int V){ memset(b,0,sizeof(b)); for(int i = 1;i <= n;i ++){ for(int j = 1;j <= n;j ++) if(a[i][j] != 0) q.push(a[i][j]); int tot = 0;while(!q.empty()){ int x = q.front();q.pop(); if(q.empty() or x != q.front()) b[i][++tot] = x; else b[i][++tot] = x * 2,q.pop(),num += x * 2; } } } void work_RIGHT(int K,int V){ memset(b,0,sizeof(b)); for(int i = 1;i <= n;i ++){ for(int j = n;j >= 1;j --) if(a[i][j] != 0) q.push(a[i][j]); int tot = n + 1;while(!q.empty()){ int x = q.front();q.pop(); if(q.empty() or x != q.front()) b[i][--tot] = x; else b[i][--tot] = x * 2,q.pop(),num += x * 2; } } } void work(){ int opt,K,V,tot = 0;while(m --){ scanf("%lld%lld%lld",&opt,&K,&V); if(opt == 0) work_UP(K,V); if(opt == 1) work_DOWN(K,V); if(opt == 2) work_LEFT(K,V); if(opt == 3) work_RIGHT(K,V); int r = 0,z = 0; for(int i = 1;i <= n;i ++){ for(int j = 1;j <= n;j ++){ if(a[i][j] != b[i][j]) z = 1; a[i][j] = b[i][j]; if(a[i][j] == 0) r ++; } } if(z == 0) break;tot ++; r = 1 + K % r;int g = 0; for(int i = 1;i <= n;i ++){ for(int j = 1;j <= n;j ++){ if(a[i][j] == 0) g ++; if(g == r) {a[i][j] = V;break;} } if(g == r) break; } } printf("%lld\n%lld\n",tot,num); } signed main(){ Input(); work(); return 0; }
T2 子集
努力完成任务才能有钱赚,有钱赚了才能吃饱饭。
特判
我们令
如果
1 | 5 | 9 | 16 | 20 | 24 |
---|---|---|---|---|---|
2 | 6 | 10 | 15 | 19 | 23 |
3 | 7 | 11 | 14 | 18 | 22 |
4 | 8 | 12 | 13 | 17 | 21 |
如果
如果 No
。把
我们先构造出前三列,然后后面那些根据偶数的构造方式进行构造。
第一列我们还是从
1 | 12 |
---|---|
2 | 13 |
3 | 14 |
4 | 8 |
5 | 9 |
6 | 10 |
7 | 11 |
应该也能看懂怎么构造。然后第三列就让前三列相等这么构造就行了。后面的按照偶数的方法构造。
收手吧,你会受伤的。
#include <bits/stdc++.h> using namespace std; int T,n,k; unordered_map < int , unordered_map < int , int > > a; int main(){ scanf("%d",&T);while(T --){ scanf("%d%d",&n,&k); if(n == k and k != 1) {puts("No");continue;} int m = n / k;a.clear(); if(m % 2 == 0){ int tot = 0;puts("Yes"); for(int j = 1;j <= m / 2;j ++){ for(int i = 1;i <= k;i ++){ a[i][j] = ++tot; } } for(int j = m / 2 + 1;j <= m;j ++){ for(int i = k;i >= 1;i --){ a[i][j] = ++tot; } } for(int i = 1;i <= k;i ++){ for(int j = 1;j <= m;j ++){ printf("%d ",a[i][j]); }puts(""); } } else{ if(n % 2 == 0) {puts("No");continue;} int tot = 0;puts("Yes"); for(int i = 1;i <= k;i ++) a[i][1] = ++tot; int z1 = k * 3,z2 = k * 3 - 1; for(int i = k / 2 + 1;i <= k;i ++) a[i][2] = ++tot,a[i][3] = z1,z1 -= 2; for(int i = 1;i <= k / 2;i ++) a[i][2] = ++tot,a[i][3] = z2,z2 -= 2; tot += k; for(int j = 4;j <= (m - 3) / 2 + 3;j ++){ for(int i = 1;i <= k;i ++){ a[i][j] = ++tot; } } for(int j = (m - 3) / 2 + 4;j <= m;j ++){ for(int i = k;i >= 1;i --){ a[i][j] = ++tot; } } for(int i = 1;i <= k;i ++){ for(int j = 1;j <= m;j ++){ printf("%d ",a[i][j]); }puts(""); } } } return 0; }
T3 混凝土粉末
我的记忆有限,不想给仇恨留有空间。
将询问离线下来,在序列下标上执行扫描线,并开一个以询问编号为下表的树状数组。
当扫描到一个修改的左端点的时候,就在树状数组这个修改的编号的位置加上其对应的
当扫描到一个询问的时候,在树状数组上二分即可(好像也算是使用了倍增的思想)。注意我们找的是这个树状数组在当前询问编号的位置前的所有位置中的
疤痕不是勋章,它们只会在下雨天发热发烫。
#include <bits/stdc++.h> #define N 1000006 #define int long long using namespace std; vector < pair < int , int > > a[N],b[N]; int n,q,ans[N];bool vis[N]; struct Set_Tree{ int c[N]; void add(int x,int y) {for(int i = x;i <= q;i += i & (-i)) c[i] += y;} int query(int x,int y){ int pos = 0,sum = 0,np; for(int i = 20;i >= 0;i --){ if((np = pos + (1 << i)) <= x and sum + c[np] < y){ sum += c[np],pos = np; } } return pos == x ? 0 : pos + 1; } }Set; signed main(){ scanf("%lld%lld",&n,&q); int opt,l,r,h,x,y;for(int i = 1;i <= q;i ++){ scanf("%lld",&opt); if(opt == 1){ scanf("%lld%lld%lld",&l,&r,&h); a[l].push_back({i,h}); a[r + 1].push_back({i,-h}); } if(opt == 2){ scanf("%lld%lld",&x,&y); b[x].push_back({i,y}); vis[i] = 1; } } for(int i = 1;i <= n;i ++){ for(auto j : a[i]) Set.add(j.first,j.second); for(auto j : b[i]) ans[j.first] = Set.query(j.first,j.second); } for(int i = 1;i <= q;i ++) if(vis[i]) printf("%lld\n",ans[i]); return 0; }
T4 排水系统
我的名字,大概是叫亚连吧。
期望 等于 每个取值 乘 得到该取值的概率的 积 的总和。
分数取模:如果模数
我们使用样例二进行解释。
下文中,我们定义点权表示这个点可以流出的污水的值,初始状态表示这个图每个点最开始的时候的点权(也就是
先使用拓扑排序,我们先把所有管道都不堵塞的时候每个点的点权求出来,我们将这求出来的点权定义为
对于下图,边权代表这个管道老化的概率。
然后,我们思考一下:对于一个管道
那么我们思路就有了,我们把这些值的期望都加到初始状态的图上,就可以得到每一个点初始状态点权的期望值,然后再在这个图上在跑一边就可以求得每个最终排水口排出的期望值。
OK,现在整体思路有了,然后我们思考一下这些值怎么计算。
我们定义
那么
继续模拟一下样例:
然后我们再把算出来的这些
然后我们再在这张图上重新跑一边即可。
可以参考着代码进行理解。
双剑,出鞘!需要我解决什么?什么都可以。
#include <bits/stdc++.h> #define N 500005 #define int long long #define MOD 998244353 using namespace std; int ksm(int a,int b){ int res = 1; while(b){ if(b & 1) res = res * a % MOD; a = a * a % MOD; b >>= 1; } return res; } int n,m,r,k,num[N],ans[N],JD,sum,C[N],R1[N],R2[N],R3[N]; queue < int > q; struct Edge{int next,to,dis;}edge[N]; int head[N],cnt; void add(int from,int to,int dis){ edge[++cnt] = (Edge){head[from],to,dis}; head[from] = cnt; } void bfs3(){ while(!q.empty()){ int x = q.front();q.pop(); int res = num[x] * ksm(C[x] % MOD,MOD - 2) % MOD; for(int i = head[x];i;i = edge[i].next){ int y = edge[i].to;num[y] += res,num[y] %= MOD; R3[y] --;if(!R3[y]) q.push(y); } } } void bfs2(){ while(!q.empty()){ int x = q.front();q.pop(); int res = ans[x] * ksm(C[x] % MOD,MOD - 2) % MOD; for(int i = head[x];i;i = edge[i].next){ int y = edge[i].to;ans[y] += res,ans[y] %= MOD; R2[y] --;if(!R2[y]) q.push(y); } } } void bfs1(){ while(!q.empty()){ int x = q.front();q.pop(); for(int i = head[x];i;i = edge[i].next){ int y = edge[i].to; int o = num[x] * ksm((C[x] - 1) % MOD,MOD - 2) % MOD; ans[x] += (C[x] * o % MOD - num[x] + MOD) % MOD * edge[i].dis % MOD * JD % MOD,ans[x] %= MOD; ans[y] += (MOD - o) % MOD * edge[i].dis % MOD * JD % MOD,ans[y] %= MOD; R1[y] --;if(!R1[y]) q.push(y); } } } signed main(){ scanf("%lld%lld%lld%lld",&n,&m,&r,&k); for(int i = 1,u,v,w;i <= k;i ++){ scanf("%lld%lld%lld",&u,&v,&w);add(u,v,w); sum += w,sum %= MOD;R1[v] ++,R2[v] ++,R3[v] ++,C[u] ++; } for(int i = 1;i <= m;i ++) num[i] = 1,q.push(i);bfs3(); JD = ksm(sum,MOD - 2); for(int i = 1;i <= m;i ++) ans[i] = 1,q.push(i);bfs1(); for(int i = 1;i <= m;i ++) q.push(i);bfs2(); for(int i = n - r + 1;i <= n;i ++) printf("%lld ",ans[i]); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步