NOIP 模拟 16
A 图
直接上 std::bitset
。
B 序列
首先赋值在加法前,加法在乘法后,一个有效的赋值可以看做一个加法,乘法的顺序无所谓,直接加最大,考虑把加法转化成乘法,那就看加的数在原数的占比,需要考虑加法的顺序,一定是先加大的,所以直接排序后转化成乘法就好了。
C 树
究极换根 DP 好题。
先看
正解就是在
求答案实际上需要的是连的树的必败点和必胜点方案数,以及对根有影响的节点数。先不考虑连第一棵树,这样每棵树都可以任意起点,设
这个东西可以轻易矩阵加速,所以现在只需要考虑如何处理出来
首先,
换根需要拆贡献,博弈论通常把记一下
#include<bits/stdc++.h> #define int long long #define fi first #define se second #define pii std::pair<int,int> #define eb emplace_back #define pb push_back typedef long long ll; typedef unsigned long long ull; std::mt19937 myrand(std::chrono::high_resolution_clock::now().time_since_epoch().count()); inline int R(int n){return myrand()%n+1;} inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;} const int N=2e5+10,mod=1e9+7,inf=1e9; inline void Min(int &x,int y){if(x>y)x=y;} inline void Max(int &x,int y){if(x<y)x=y;} inline void W(int &x,int y){x=(x+y)%mod;} int n,num[2],D,n0,n1; std::vector<int> e[N]; struct NODE{int num,f,g0,g1;}a[N],r[N],zc[N]; inline void Pass(int x,int fa){ a[x]={0,0,0,0}; for(int v:e[x]){ if(v==fa)continue; a[x].f|=!a[v].f;a[x].num+=!a[v].f; } a[x].g1++; for(int v:e[x]){ if(v==fa)continue; if(a[x].num>1)W(a[x].g1,a[v].g0+a[v].g1); if(a[x].num==1){ if(a[v].f)W(a[x].g1,a[v].g0+a[v].g1); else W(a[x].g0,a[v].g1),W(a[x].g1,a[v].g0); }if(!a[x].num)W(a[x].g1,a[v].g0),W(a[x].g0,a[v].g1); } } inline void dfs(int x,int fa){for(int v:e[x])if(v^fa)dfs(v,x);Pass(x,fa);zc[x]=a[x];} inline void change(int x,int fa){ if(x==1)r[x]=a[x]; else{ if(!a[x].f){ if(a[fa].num<=2)Pass(fa,x); else a[fa].num--,a[fa].g1-=a[x].g0+a[x].g1; }else{ if(a[fa].f)a[fa].g1-=a[x].g0+a[x].g1; else a[fa].g1-=a[x].g0,a[fa].g0-=a[x].g1; } Pass(x,0);r[x]=a[x]; } for(int v:e[x])if(v^fa)change(v,x),a[x]=r[x];a[x]=zc[x]; } struct MAT{ int a[2][2]; inline MAT(){memset(a,0,sizeof(a));} inline MAT operator*(const MAT&B)const{ MAT res;int r;for(int i=0;i<2;++i) for(int k=0;k<2;++k){ r=a[i][k];for(int j=0;j<2;++j)W(res.a[i][j],r*B.a[k][j]); }return res; } }base,ans; inline void work(){ for(int i=1;i<=n;++i)num[r[i].f]++,W(n0,r[i].g0),W(n1,r[i].g1); ans.a[0][0]=num[0],ans.a[0][1]=num[1]; base.a[0][0]=n0,base.a[1][0]=n*num[0]%mod,base.a[0][1]=n1,base.a[1][1]=n*num[1]%mod; for(;D;D>>=1,base=base*base)if(D&1)ans=ans*base;int ANS=r[1].g1*ans.a[0][0]+n*ans.a[0][1]*r[1].f; std::cout<<(ANS%mod+mod)%mod<<'\n'; } signed main(){ freopen("c.in","r",stdin);freopen("c.out","w",stdout); std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0); n=read();D=read()-1;for(int i=1;i<n;++i){int u=read(),v=read();e[u].eb(v);e[v].eb(u);} dfs(1,0);change(1,0);work(); }
D 字符串
简单手玩发现相邻的两个字母如果逆序一定会产生一个贡献,然后暴力线段树维护
总结
打成傻逼了,T2 忘了特判挂了 60pts,T4 根本没去仔细观察,给自己设限了,傻卵。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具