关于mod , define , const

本文分享了作者在调试过程中积累的宝贵经验,包括进行模运算时选择合适模数的重要性,以及在编程中使用const而非define的优点,帮助读者避免潜在的bug。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 今天下午一下午都在调一个题,最后终于知道是什么问题了。。得到了宝贵的经验。。

1.虽然题中要求mod 1000000007 但是!运算时一定要 mod更大的数!!

如 输出ans, 先算出 n 然后 ans = n / 2; 则 n 运算时一定yaomod 不小于 2 *10000000007的数!!!!

2.const 是个好同志啊。。define 会造成然人崩溃的bug!!

#include<bits/stdc++.h> #define ull unsigned long long #define ll long long #define pb push_back #define mkp make_pair #define fi first #define se second #define inf 1000000000 #define infll 1000000000000000000ll #define pii pair<int,int> #define rep(i,a,b,c) for(int i=(a);i<=(b);i+=(c)) #define per(i,a,b,c) for(int i=(a);i>=(b);i-=(c)) #define F(i,a,b) for(int i=a,i##end=b;i<=i##end;i++) #define dF(i,a,b) for(int i=a,i##end=b;i>=i##end;i--) #define cmh(sjy) while(sjy--) #define lowbit(x) (x&(-x)) #define HH printf("\n") #define eb emplace_back #define poly vector<int> #define SZ(x) ((int)x.size() using namespace std; // 快速取模幂运算 template<typename T>inline void chkmax(T &x,const T &y){ x=std::max(x,y); } template<typename T>inline void chkmin(T &x,const T &y){ x=std::min(x,y); } const int mod=998244353, maxn=100005; void fre(){ freopen("mountain.in","r",stdin),freopen("mountain.out","w",stdout); } // 快速幂函数 inline int qpow(int x,ll y){ int rt=1; for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) rt=1ll*rt*x%mod; return rt; } // 加法、减法、乘法的封装,带模数处理 inline void inc(int &x,const int y){ x=(x+y>=mod)?(x+y-mod):(x+y); } inline void dec(int &x,const int y){ x=(x>=y)?(x-y):(x+mod-y); } inline void mul(int &x,const int y){ x=1ll*x*y%mod; } inline int add(const int x,const int y){ return (x+y>=mod)?(x+y-mod):(x+y); } inline int sub(const int x,const int y){ return (x>=y)?(x-y):(x+mod-y); } inline int prod(const int x,const int y){ return 1ll*x*y%mod; } int n, dfn[maxn], siz[maxn], tim, stk[maxn], top, dep[maxn], f[maxn], fa[maxn]; int anc[maxn][20], mn[maxn][20]; // 倍增祖先数组 int ul[maxn], ur[maxn], uh[maxn], lim[maxn], pre[maxn], fr[maxn], tol[maxn], tor[maxn], diff[maxn], th[maxn]; vector<int>g[maxn], tmp, nxt[maxn]; // 子树结构 vector<pii>qu[maxn]; // 查询队列 // 第一次DFS:预处理树结构、深度、倍增表等 void dfs1(int u){ dfn[u]=++tim, siz[u]=1; stk[top++]=u; tmp.push_back(u); // 找到某个祖先节点 v,满足其限制条件 auto find=[&](int k){ return k>dep[u]?0:stk[dep[u]-k]; }; int v=u; dF(i,18,0) if(anc[v][i]&&mn[v][i]>=lim[u]) v=anc[v][i]; fr[u]=fa[v], nxt[fr[u]].push_back(u); // 处理冲刺区间 [l_i, r_i] const int L=dep[u]-ul[u]+1, R=dep[u]-ur[u]; // 获取当前节点的“休息目标” th[u]=find(uh[u]+1); if(lim[u]>=R){ int p=u,to=find(ur[u]+1); dF(i,18,0) if(anc[p][i]&&mn[p][i]>=R)p=anc[p][i]; qu[to].push_back(mkp(u,mod-1)), qu[to].push_back(mkp(fa[p],1)); inc(diff[fa[p]],mod-1); }else inc(diff[u],mod-1); if(lim[u]>=L){ int p=u,to=find(ul[u]); dF(i,18,0) if(anc[p][i]&&mn[p][i]>=L)p=anc[p][i]; qu[to].push_back(mkp(u,1)), qu[to].push_back(mkp(fa[p],mod-1)); inc(diff[fa[p]],1); }else inc(diff[u],1); // 遍历子树 for(int v:g[u])dfs1(v),siz[u]+=siz[v]; --top; } // 第三次DFS:进行差分标记合并 void dfs3(int u){ for(int v:nxt[u])dfs3(v),inc(diff[u],diff[v]); if(!u)return; qu[th[u]].push_back(mkp(u,diff[u])); qu[th[u]].push_back(mkp(fr[u],sub(0,diff[u]))); } // 树状数组实现前缀查询 namespace DS{ int t[maxn]; void init(){ memset(t,0,sizeof t); } void add(int x,int y){ if(x)for(;x<=n;x+=lowbit(x))inc(t[x],y); } int query(int x){ int R=0;for(;x;x^=lowbit(x))inc(R,t[x]);return R; } int query(int l,int r){ return l>r?0:sub(query(r),query(l-1)); } } // 第二次DFS:最终DP计算 void dfs2(int u){ f[u]=(u==1)?1:DS::query(dfn[u],dfn[u]+siz[u]-1); pre[u]=add(pre[fa[u]],f[u]); // 将查询结果更新进树状数组 for(auto [x,y]:qu[u])DS::add(dfn[x],1ll*y*pre[u]%mod); // 遍历子树 for(int v:g[u])dfs2(v); } // 主处理函数:读入数据并调用各部分 void solve(){ cin>>n, tim=top=0, dep[0]=-1; F(i,0,n) g[i].clear(), fr[i]=diff[i]=0, qu[i].clear(), nxt[i].clear(); F(i,2,n) cin>>fa[i]>>ul[i]>>ur[i]>>uh[i], dep[i]=dep[fa[i]]+1, lim[i]=dep[i]-uh[i]-1; // 构建图结构 F(i,2,n) g[fa[i]].push_back(i); // 倍增表预处理 F(i,1,n) anc[i][0]=fa[i], mn[i][0]=lim[fa[i]]; F(j,1,18) F(i,1,n) anc[i][j]=anc[anc[i][j-1]][j-1], mn[i][j]=min(mn[i][j-1], mn[anc[i][j-1]][j-1]); // DFS遍历 dfs1(1), dfs3(0); DS::init(); // DP计算 dfs2(1); // 输出答案 F(i,2,n) cout<<f[i]<<' '; cout<<endl; } int testid; // 主函数 signed main(){ fre(), ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int zsy=1; cin>>testid>>zsy; F(____,1,zsy)solve(); // 多组测试数据循环 } 这份代码请给dfs1里面再添加一些注释
最新发布
07-04
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值