2025多校冲刺省选模拟赛15 && 2025省选模拟12
2025多校冲刺省选模拟赛15
A. 小 F 的疑惑
-
等省选后再来改。
点击查看 std
#include <cmath> #include <cstdio> #include <iostream> #include <vector> const int nn = 5e5 + 5; int prime[nn], notprime[nn], mu[nn], f[nn], g[nn], sum[8][30][nn]; std::vector<int> facs[nn]; void init() { int n = 500000; notprime[0] = notprime[1] = mu[1] = 1; for (int i = 2; i <= n; i++) { if (!notprime[i]) { prime[++prime[0]] = i; mu[i] = -1; } for (int j = 1; j <= prime[0] && i * prime[j] <= n; j++) { notprime[i * prime[j]] = 1; if (i % prime[j] == 0) break; mu[i * prime[j]] = -mu[i]; } } for (int i = 1; i * i <= n; i++) for (int j = i * i; j <= n; j += i * i) f[j] = i; for (int i = 2; i * i * i <= n; i++) for (int j = i * i * i; j <= n; j += i * i * i) g[j] = i; n = 20000; for (int i = 1; i <= n; i++) for (int j = i; j <= n; j += i) facs[j].push_back(i); } typedef long long ll; ll sqrt2(ll n) { ll ret = sqrt(n); while (ret * ret > n) ret--; while ((ret + 1) * (ret + 1) <= n) ret++; return ret; } ll sqrt3(ll n) { ll ret = cbrt(n); while (ret * ret * ret > n) ret--; while ((ret + 1) * (ret + 1) * (ret + 1) <= n) ret++; return ret; } ll solve(ll n) { ll n1 = sqrt3(sqrt2(sqrt2(n))), n2 = sqrt3(n), ret = 0; for (int i = 1; i * (i + 1ll) * (i + 1) <= n; i++) if (f[i] == 1) ret += sqrt2(n / i) - i; for (int i = 1; i <= 5; i++) for (int j = 1; j <= n1; j++) for (int k = 1; i * k <= n2; k++) sum[i][j][k] = sum[i][j][k - 1] + (f[i * k] <= j); // printf("now %lld %lld\n", n, ret); for (int i = 1; i * (i + 1ll) * (i + 1) * (i + 1) <= n; i++) { if (g[i]) continue; int lim1 = sqrt3(i); for (int x : facs[i]) { int y = i / x, lim2 = lim1 / x / f[y]; if (!lim2) continue; ll lim3 = sqrt3(n / i) / x; for (int z : facs[y]) { if (mu[z] == 0) continue; int cnt = 0; if (z <= 5) cnt = sum[z][lim2][lim3 / z] - sum[z][lim2][y / z]; else for (int l = y + z; l <= lim3; l += z) cnt += f[l] <= lim2; ret += cnt * mu[z]; } } } return ret; } int main() { freopen("power.in", "r", stdin); freopen("power.out", "w", stdout); int t; scanf("%d", &t); ll l, r; init(); while (t--) { scanf("%lld %lld", &l, &r); printf("%lld\n", solve(r) - solve(l - 1)); } }
B. 城市规划
-
数据中提到了可能会有重复的点,但一些 Corner Case 还是没卡。
-
需要借助
inline
和#pragma GCC optimize(3)
的力量。点击查看代码
#pragma GCC optimize(3) const ll dx[4][3]={{1,0,0},{1,0,0},{-1,0,0},{-1,0,0}},dy[4][3]={{0,-1,0},{0,1,0},{0,-1,0},{0,1,0}}; ll dfn[1610],low[1610],ins[1610],col[1610],x[2][3],y[2][3],tot,scc_cnt,n,w,h; pair<ll,ll>a[1610],z[2][3]; stack<ll>s; vector<ll>e[1610]; inline void add(ll u,ll v) { e[u].push_back(v); } inline void tarjan(ll x) { tot++; dfn[x]=low[x]=tot; ins[x]=1; s.push(x); for(ll i=0;i<e[x].size();i++) { if(dfn[e[x][i]]==0) { tarjan(e[x][i]); low[x]=min(low[x],low[e[x][i]]); } else { if(ins[e[x][i]]==1) { low[x]=min(low[x],dfn[e[x][i]]); } } } if(dfn[x]==low[x]) { scc_cnt++; ll tmp=0; while(x!=tmp) { tmp=s.top(); ins[tmp]=0; col[tmp]=scc_cnt; s.pop(); } } } inline bool out_of_bounds(ll x,ll y,ll op,ll mid) { for(ll i=0;i<=1;i++) { if(x+dx[op][i]*mid<0||x+dx[op][i]*mid>w||y+dy[op][i]*mid<0||y+dy[op][i]*mid>h) return true; } return false; } inline bool line_cross(ll x1,ll y1,ll x2,ll y2,ll _x1,ll _y1,ll _x2,ll _y2) { if(x1==x2&&_x1==_x2) { return ((x1==_x1)&&((min(y1,y2)<_y1&&_y1<max(y1,y2))||(min(y1,y2)<_y2&&_y2<max(y1,y2)))); } if(_x1==_x2) { swap(x1,_x1); swap(y1,_y1); swap(x2,_x2); swap(y2,_y2); } if(x1==x2) { double _k=1.0*(_y2-_y1)/(_x2-_x1),_b=_y1-_x1*_k,y=_k*x1+_b; return (_x1<x1&&x1<_x2&&min(y1,y2)<y&&y<max(y1,y2)); } double k=1.0*(y2-y1)/(x2-x1),b=y1-x1*k,_k=1.0*(_y2-_y1)/(_x2-_x1),_b=_y1-_x1*_k; if(k==_k) return false; double x=(_b-b)/(k-_k); return (min(x1,x2)<x&&x<max(x1,x2)&&min(_x1,_x2)<x&&x<max(_x1,_x2)); } inline bool triangle_cross(ll x1,ll y1,ll op1,ll x2,ll y2,ll op2,ll mid) { for(ll i=0;i<=2;i++) { x[0][i]=x1+dx[op1][i]*mid; y[0][i]=y1+dy[op1][i]*mid; x[1][i]=x2+dx[op2][i]*mid; y[1][i]=y2+dy[op2][i]*mid; } for(ll i=0;i<=2;i++) { for(ll j=0;j<=2;j++) { if(line_cross(x[0][i],y[0][i],x[0][(i+1)%3],y[0][(i+1)%3], x[1][j],y[1][j],x[1][(j+1)%3],y[1][(j+1)%3])==true) { return true; } } } return false; } inline bool check(ll mid) { for(ll i=1;i<=8*n;i++) e[i].clear(); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(ins,0,sizeof(ins)); memset(col,0,sizeof(col)); tot=scc_cnt=0; while(s.empty()==0) s.pop(); for(ll i=1;i<=n;i++) { for(ll j=0;j<=3;j++) { add(i+j*n,i+(3-j)*n+4*n); add(i+j*n+4*n,i+(3-j)*n); if(out_of_bounds(a[i].first,a[i].second,j,mid)==true) add(i+j*n,i+j*n+4*n); } } for(ll i=1;i<=n;i++) { for(ll j=i+1;j<=n;j++) { for(ll u=0;u<=3;u++) { for(ll v=0;v<=3;v++) { if((a[i]==a[j]&&u==v)||triangle_cross(a[i].first,a[i].second,u, a[j].first,a[j].second,v,mid)==true) { add(i+u*n,j+v*n+4*n); add(j+v*n,i+u*n+4*n); } } } } } for(ll i=1;i<=8*n;i++) if(dfn[i]==0) tarjan(i); for(ll i=1;i<=4*n;i++) if(col[i]==col[i+4*n]) return false; return true; } int main() { #define Isaac #ifdef Isaac freopen("city.in","r",stdin); freopen("city.out","w",stdout); #endif ll l=0,r,ans=0,mid,i; cin>>w>>h>>n; r=min(w,h); w*=2; h*=2; for(i=1;i<=n;i++) { cin>>a[i].first>>a[i].second; a[i].first*=2; a[i].second*=2; } while(l<=r) { mid=(l+r)/2; if(check(mid)==true) { ans=mid; l=mid+1; } else { r=mid-1; } } cout<<ans<<".00"<<endl; return 0; }
HZTG5883. 机关
HZTG3024. 发烧(fever)
C. 小 F 的序列
-
等省选后再来改。
点击查看 std
/* Author: haoyipeng Submission: https://uoj.ac/submission/392285 */ #include <algorithm> #include <cstdio> #include <cstring> #include <iostream> #include <vector> using namespace std; const int N = 3e5 + 5, M = 1e6 + 5; int read() { int x = 0, f = 1; char ch; while (!isdigit(ch = getchar())) (ch == '-') && (f = -f); for (x = ch ^ 48; isdigit(ch = getchar()); x = (x << 3) + (x << 1) + (ch ^ 48)); return x * f; } vector<int> d[M]; int n, m, q, x, y, l, r, ans, a[N], f[N], op[N], val[N], pos[M], vis[M], cnt2[25], cnt[N][25]; /* f[i] 表示以i为开头的 maxlen; cnt[i][j] 表示以i为开头,len = j的"上升倍数子序列"的nxt的个数; cnt2[x] 长度为 x 的(最长)上升倍数子序列开头个数; 实际上是 j > i 且 f[j] == j-1 的f[j]个数; why? 主要是因为直接维护nxt非常麻烦,但是我们的dp中只要保留最优的转移方式; 而且如果一个nxt改了,复杂度直接就成了O(ans); 而新的状态是O(1); */ void out() { for (ans = 1; cnt2[ans + 1]; ++ans); printf("%d %d\n", ans, cnt2[ans]); } void pf(int i) { memset(cnt[i], 0, sizeof(cnt[i])); cnt[i][f[i] = 1] = 1; for (int j = a[i] * 2; j <= m; j += a[i]) if (pos[j]) ++cnt[i][f[pos[j]] + 1]; // pos[j] 的数位置保证在 [q + i + 1, q + n]; for (; cnt[i][f[i] + 1]; ++f[i]); ++cnt2[f[i]]; // 长度为 f[i] 的上升倍数子序列开头个数增加; } void pb(int i) { memset(cnt[i], 0, sizeof(cnt[i])); cnt[i][f[i] = 1] = 1; ++cnt2[f[i]]; for (int j = 0; j < d[a[i]].size(); ++j) { // 枚举约数 x; if (!(x = pos[d[a[i]][j]])) continue; ++cnt[x][2]; if (!cnt[x][f[x] + 1]) continue; --cnt2[f[x]]; ++cnt2[++f[x]]; for (int k = 0; k < d[a[x]].size(); ++k) { // 枚举约数 a[x] 的约数 y, 且 y的位置在 x 前; if ((y = pos[d[a[x]][k]]) && y < x) --cnt[y][f[x]], ++cnt[y][f[x] + 1]; } } } void ppf(int i) { --cnt2[f[i]]; } // 消去影响, 长度为 f[i] 的上升倍数子序列开头个数增加; void ppb(int i) { --cnt2[f[i]]; for (int j = 0, k; j < d[a[i]].size(); ++j) { // 消去对前面数的影响; if (!(x = pos[d[a[i]][j]])) continue; --cnt[x][2]; if (cnt[x][f[x]]) continue; --cnt2[f[x]], ++cnt2[--f[x]]; for (int k = 0; k < d[a[x]].size(); ++k) { // 枚举约数 a[x] 的约数 y, 且 y的位置在 x 前; if ((y = pos[d[a[x]][k]]) && y < x) --cnt[y][f[x] + 2], ++cnt[y][f[x] + 1]; } } } int main() { freopen("seq.in", "r", stdin); freopen("seq.out", "w", stdout); n = read(); m = read(); q = read(); l = q + 1; r = q + n; for (int i = 1; i <= n; ++i) vis[a[q + i] = read()] = 1; // vis[i] 表示 i 是否会出现在序列中; for (int i = 1; i <= q; ++i) if ((op[i] = read()) < 2) vis[val[i] = read()] = 1; // val[i] 表示第 i 次操作加入的数; for (int i = m; i; --i) { // 枚举值域中出现过的数; if (!vis[i]) continue; for (int j = (i << 1); j <= m; j += i) if (vis[j]) d[j].push_back(i); // d[i] 为序列中出现过的 i 的约数; } for (int i = r; i >= l; --i) pf(i), pos[a[i]] = i; out(); for (int i = 1; i <= q; ++i) { if (op[i] == 0) a[--l] = val[i], pos[a[l]] = l, pf(l); if (op[i] == 1) a[++r] = val[i], pos[a[r]] = r, pb(r); if (op[i] == 2) pos[a[l]] = 0, ppf(l++); if (op[i] == 3) pos[a[r]] = 0, ppb(r--); out(); } // pos[i] 保证 i 在当前的 A 序列中; return 0; }
2025省选模拟12
P1019. 国际象棋
-
观察到每条对角线上有且仅有一个
,且合法局面下的 一定构成了一段从 到 的路径,途中不经过 。 -
从下往上考虑每条对角线的贡献,如果有
,那么其他位置上一定是 ,分段统计不经过 的方案数即可。点击查看代码
const int p=1000000007; int f[5010][5010],sx[10010],sy[10010],cnt[10010]; char s[5010][5010]; int solve(int x1,int y1,int x2,int y2) { f[x1][y1]=1; for(int i=x1;i<=x2;i++) { for(int j=y1;j<=y2;j++) { if(i+1<=x2&&s[i+1][j]!='1') f[i+1][j]=(f[i+1][j]+f[i][j])%p; if(j+1<=y2&&s[i][j+1]!='1') f[i][j+1]=(f[i][j+1]+f[i][j])%p; } } return (x1<=x2&&y1<=y2)*f[x2][y2]; } int main() { #define Isaac #ifdef Isaac freopen("chess.in","r",stdin); freopen("chess.out","w",stdout); #endif int n,m,ans=1,x=1,y=1,i,j; cin>>n>>m; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) cin>>s[n-i+1][j]; } if(s[1][1]=='1'||s[n][m]=='1') cout<<0<<endl; else { s[1][1]=s[n][m]='0'; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(s[i][j]=='0') { cnt[i+j]++; sx[i+j]=i; sy[i+j]=j; } } } for(i=3;i<=n+m&&ans!=0;i++) { if(cnt[i]>=2) ans=0; if(cnt[i]==1) { ans=1ll*ans*solve(x,y,sx[i],sy[i])%p; x=sx[i]; y=sy[i]; } } cout<<ans<<endl; } return 0; }
P1028. 好段子
-
因为没有
和数据,所以只好口胡。- 顺延 CF997E Good Subsegments 中扫描线后线段树维护历史版本和的做法,将计算被加了多少次的懒惰标记(时间懒惰标记)从原来的
改成 即可。 - 极限数据下跑了
,如果需要进一步卡常的话就把部分long long
改成int
。答案值域达到了 ,可能需要unsigned long long
。
点击查看代码
ll a[500010],ans[500010]; vector<pair<ll,ll> >q[500010]; stack<ll>s1,s2; struct SMT { struct SegmentTree { ll minn,num,hsum,tlazy,lazy; }tree[2000010]; #define lson(rt) (rt<<1) #define rson(rt) (rt<<1|1) void pushup(ll rt) { tree[rt].minn=min(tree[lson(rt)].minn,tree[rson(rt)].minn); tree[rt].num=(tree[lson(rt)].minn==tree[rt].minn)*tree[lson(rt)].num+(tree[rson(rt)].minn==tree[rt].minn)*tree[rson(rt)].num; tree[rt].hsum=tree[lson(rt)].hsum+tree[rson(rt)].hsum; } void build(ll rt,ll l,ll r) { if(l==r) { tree[rt].minn=0; tree[rt].num=1; return; } ll mid=(l+r)/2; build(lson(rt),l,mid); build(rson(rt),mid+1,r); pushup(rt); } void pushlazy(ll rt,ll lazy,ll tlazy,ll minn) { tree[rt].minn+=lazy; tree[rt].lazy+=lazy; if(tree[rt].minn==minn) { tree[rt].hsum+=tlazy*tree[rt].num; tree[rt].tlazy+=tlazy; } } void pushdown(ll rt) { pushlazy(lson(rt),tree[rt].lazy,tree[rt].tlazy,tree[rt].minn); pushlazy(rson(rt),tree[rt].lazy,tree[rt].tlazy,tree[rt].minn); tree[rt].lazy=tree[rt].tlazy=0; } void update_val(ll rt,ll l,ll r,ll x,ll y,ll val) { if(x<=l&&r<=y) { tree[rt].minn+=val; tree[rt].lazy+=val; return; } pushdown(rt); ll mid=(l+r)/2; if(x<=mid) update_val(lson(rt),l,mid,x,y,val); if(y>mid) update_val(rson(rt),mid+1,r,x,y,val); pushup(rt); } void update_tim(ll rt,ll l,ll r,ll x,ll y,ll val) { if(x<=l&&r<=y) { if(tree[rt].minn==0) { tree[rt].hsum+=val*tree[rt].num; tree[rt].tlazy+=val; } return; } pushdown(rt); ll mid=(l+r)/2; if(x<=mid) update_tim(lson(rt),l,mid,x,y,val); if(y>mid) update_tim(rson(rt),mid+1,r,x,y,val); pushup(rt); } ll query(ll rt,ll l,ll r,ll x,ll y) { if(x<=l&&r<=y) return tree[rt].hsum; pushdown(rt); ll mid=(l+r)/2,ans=0; if(x<=mid) ans+=query(lson(rt),l,mid,x,y); if(y>mid) ans+=query(rson(rt),mid+1,r,x,y); return ans; } }T; int main() { #define Isaac #ifdef Isaac freopen("seq.in","r",stdin); freopen("seq.out","w",stdout); #endif ll n,m,l,r,tmp,i,j; scanf("%lld",&n); for(i=1;i<=n;i++) scanf("%lld",&a[i]); scanf("%lld",&m); for(i=1;i<=m;i++) { scanf("%lld%lld",&l,&r); q[r].push_back(make_pair(l,i)); } T.build(1,1,n); for(i=1;i<=n;i++) { while(s1.empty()==0&&a[s1.top()]>a[i]) { tmp=s1.top(); s1.pop(); T.update_val(1,1,n,((s1.empty()==0)?s1.top():0)+1,tmp,a[tmp]-a[i]); } while(s2.empty()==0&&a[s2.top()]<a[i]) { tmp=s2.top(); s2.pop(); T.update_val(1,1,n,((s2.empty()==0)?s2.top():0)+1,tmp,a[i]-a[tmp]); } s1.push(i); s2.push(i); if(i-1>=1) T.update_val(1,1,n,1,i-1,-1); T.update_tim(1,1,n,1,i,i); for(j=0;j<q[i].size();j++) ans[q[i][j].second]=T.query(1,1,n,q[i][j].first,i); } for(i=1;i<=m;i++) printf("%lld\n",ans[i]); return 0; }
- 顺延 CF997E Good Subsegments 中扫描线后线段树维护历史版本和的做法,将计算被加了多少次的懒惰标记(时间懒惰标记)从原来的
P1020. 樱花树
-
先不管某个点在操作序列上是否出现及出现在哪个位置,在加入答案时再选择是否要加入操作序列。
-
设
表示以 为根的子树内进行 次操作不必全部删完的方案数,可以先不管 的影响树形背包转移,然后再通过 算入 的影响。设 表示以 为根的子树内进行 次操作不必全部删完,其中不操作 这条根链上的点的方案数,转移同理。 -
对于
这条根链上的点,如果加入操作序列则往下走的所有点后续不可能再被加入。进行特殊转移,若当前节点不操作则可以直接继承父亲节点的信息,否则一个后缀都可以进行转移,使用后缀和优化优化时间复杂度。接着类似背包将不操作 这条根链上的点的贡献统计即可。点击查看代码
const int p=1000000007; struct node { int nxt,to; }e[10010]; int head[5010],siz[5010],f[5010][5010],C[5010][5010],w[5010],g[2][5010],vis[5010],cnt=0; vector<int>s,d; void add(int u,int v) { cnt++; e[cnt]=(node){head[u],v}; head[u]=cnt; } void dfs(int x,int fa,int _x) { s.push_back(x); if(x==_x) d=s; f[x][0]=1; for(int i=head[x];i!=0;i=e[i].nxt) { if(e[i].to!=fa) { dfs(e[i].to,x,_x); for(int j=siz[x];j>=0;j--) { for(int k=siz[e[i].to];k>=1;k--) f[x][j+k]=(f[x][j+k]+1ll*f[x][j]*f[e[i].to][k]%p*C[j+k][k]%p)%p; } siz[x]+=siz[e[i].to]; } } siz[x]++; for(int i=siz[x];i>=1;i--) f[x][i]=(f[x][i-1]+f[x][i])%p; s.pop_back(); } int del(int x) { memset(w,0,sizeof(w)); w[0]=1; int siz_x=0; for(int i=head[x];i!=0;i=e[i].nxt) { if(vis[e[i].to]==0) { siz_x+=siz[e[i].to]; for(int j=siz_x;j>=0;j--) { for(int k=siz[e[i].to];k>=1;k--) w[j+k]=(w[j+k]+1ll*w[j]*f[e[i].to][k]%p*C[j+k][k]%p)%p; } } } return siz_x; } int main() { #define Isaac #ifdef Isaac freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); #endif int n,m,x,u,v,siz_x,sum,i,j,k; cin>>n>>m>>x; C[0][0]=C[1][0]=C[1][1]=1; for(i=2;i<=n;i++) { cin>>u>>v; add(u,v); add(v,u); C[i][0]=1; for(j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%p; } dfs(1,0,x); for(i=0;i<d.size();i++) vis[d[i]]=1; del(1); for(i=0;i<=n-1;i++) g[0][i]=w[i]; for(i=1;i<d.size();i++) { siz_x=del(d[i]); sum=0; for(j=n-1;j>=0;j--) { sum=(sum+g[(i-1)&1][j])%p; if(i==d.size()-1) g[i&1][j]=sum; else g[i&1][j]=(g[(i-1)&1][j]+sum)%p; } for(j=n-1;j>=0;j--) { if(g[(i-1)&1][j]!=0) { for(k=siz_x;k>=1;k--) if(j+k<=n-1) g[i&1][j+k]=(g[i&1][j+k]+1ll*g[i&1][j]*w[k]%p*C[j+k][k]%p)%p; } } } cout<<g[(d.size()-1)&1][m-1]<<endl; return 0; }
P1021. 长颈鹿会面
总结
- 参赛体验极差。
下没有虚拟机和双系统,被迫使用 ,中途想要对拍发现./可执行文件.exe
用不了,捣鼓了半天 和 无果,无奈使用 终端,但因为 什么插件都没有实际执行的时候出了一堆奇奇怪怪的问题。
不知道自己 的部分分挂在哪里了。
后记
- 因原
道题目都声称之前见过或做过弱化版, 把整套题都换了,原来那套留给我们做练习题用。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18727868,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具