2023年多校联训NOIP层测试7+【LGR-149-Div.3】洛谷基础赛 #2 & qw Round -1
普及模拟3
\(T1\) 最大生成树 \(100pts\)
- 简化题意:给定一个 \(n(1 \le n \le 1 \times 10^5)\) 个点的完全图,给定各点的点权 \(a_i(1 \le i \le n)\) ,两点间的边权为 \(|a_i-a_j|\) ,求该图的最大生成树。
- 正解:贪心,考虑到一个点对答案产生的贡献为 \(\max(a_i-\min\limits_{j=1}^{n} \{ a_j \},\max\limits_{j=1}^{n} \{ a_j \}-a_i)\) ,又因为是完全图,易证得连边后一定是符合题意的解。
ll a[100001];//十年OI一场空,不开long long见祖宗
int main()
{
ll n,i,ans=0;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
for(i=1;i<=n-1;i++)//只需要n-1条边
{
ans+=max(a[n]-a[i],a[i]-a[1]);
}
cout<<ans<<endl;
return 0;
}
- 貌似是首A。
- 扩展: @xrlong 的 \(idea\) :原题目除最大生成树改为最小生成树外不变。
- 解法:类似 2023年多校联训NOIP层测试7,集训欢乐赛,绝对欢乐,童叟无欺 T4 滑冰,考虑对所有的点按照点权进行排序,相邻两个点进行连边显然最优,消去之间的影响,最终 \(\max_{i=1}^{n} \{ a_{i} \}-\min_{i=1}^{n} \{ a_{i} \}\) 即为所求。
\(T2\) 红黑树 \(80pts\)
- 简化题意:给定一棵 \(n(1 \le n \le 1 \times 10^5)\) 个点的有根树, \(1\) 为根节点,初始每个点都是红色,有 \(n\) 次操作,每次操作会把 \(p_i\) 变成黑色,保证操作序列 \(p\) 是一个排列,即每次操作的点都不相同。每次操作完成后,你需要输出有多少个子树是红黑子树,即子树内既包含黑点又包含红点。
- 本题中的红黑树与 红黑树 无任何关系。
- 部分分:
- \(20pts\) :对链的情况特判。
- \(80pts\)(在线做法) :一遍 \(DFS\) 处理出以 \(i(1 \le i \le n)\) 为根的子树大小,每次修改暴力跳父亲直到根节点,卡在了链的测试点上,复杂度为 \(O(n^2)\) 。
struct node
{
int nxt,to;
}e[200001];
int head[200001],siz[200001],fa[200001],vis[200001],cnt=0;
void add(int u,int v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs(int x,int father)
{
fa[x]=father;
for(int i=head[x];i!=0;i=e[i].nxt)
{
if(e[i].to!=father)
{
dfs(e[i].to,x);
siz[x]+=siz[e[i].to]+1;
}
}
}
int main()
{
int n,i,j,u,v,p,ans=0;
cin>>n;
for(i=1;i<=n-1;i++)
{
cin>>u;
v=i+1;
add(u,v);
}
dfs(1,0);
for(i=1;i<=n;i++)
{
siz[i]++;
}
for(i=1;i<=n;i++)
{
cin>>p;
for(j=p;j!=0;j=fa[j])
{
siz[j]--;
if(vis[j]==0)
{
if(1<=siz[j])
{
vis[j]=1;
ans++;
}
}
else
{
if(!(1<=siz[j]))
{
vis[j]=0;
ans--;
}
}
}
cout<<ans<<" ";
}
return 0;
}
- 正解(离线做法):
- 前置知识:红黑子树的产生与消失都是由改变颜色的这个点造成的。
- 例如,把节点 \(x\) 变成黑色后,对于所有包含 \(x\) 的子树 \(T\) ,如果 \(x\) 是该子树内第一个变成黑色的点,那么 \(x\) 会让 \(T\) 变成红黑子树;如果 \(x\) 是该子树内最后一个红色的点,那么 \(x\) 会让 \(T\) 变成非红黑子树。
- 记录下这棵子树中黑点最先出现和最后一个红点变成黑点的时候。
- 做法一:暴力跳父亲时跳到某个点时,若这个点既不是以这个点的父亲节点为根的子树内最先出现的黑点,也不是最后一个变成黑点的红点时就没有必要跳了,因为不会对答案产生贡献了(这里可能有些绕口,自己可以画图模拟一下)。
- 复杂度貌似很神奇,官方题解写的是 \(O(n)\) 。
struct node
{
int nxt,to;
}e[200001];
int head[200001],minn[200001],maxx[200001],p[200001],id[200001],fa[200001],cnt=0;//minn表示(····)最早出现,maxx表示最后一个(····)消失
void add(int u,int v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs(int x)
{
minn[x]=maxx[x]=id[x];
for(int i=head[x];i!=0;i=e[i].nxt)
{
dfs(e[i].to);
minn[x]=min(minn[x],minn[e[i].to]);
maxx[x]=max(maxx[x],maxx[e[i].to]);
}
}
int main()
{
int n,i,j,u,v,ans=0,flag;
cin>>n;
for(i=1;i<=n-1;i++)
{
cin>>u;
v=i+1;
fa[v]=u;
add(u,v);
}
for(i=1;i<=n;i++)
{
cin>>p[i];
id[p[i]]=i;
}
dfs(1);
for(i=1;i<=n;i++)
{
for(j=p[i];j!=0;j=fa[j])//暴力跳父亲
{
flag=0;
if(minn[j]==id[p[i]])
{
ans++;
flag=1;
}
if(maxx[j]==id[p[i]])
{
ans--;
flag=1;
}
if(flag==0)
{
break;
}
}
cout<<ans<<" ";
}
return 0;
}
- 复杂度貌似很神奇,官方题解写的是 \(O(n)\) 。
- 做法二:进行差分维护一下。————隔壁 @xrlong 的做法
- 树状数组的区间修改单点查询操作
struct node
{
int nxt,to;
}e[200001];
int head[200001],minn[200001],maxx[200001],p[200001],id[200001],c[400001],cnt=0;
int lowbit(int x)
{
return (x&(-x));
}
void add(int u,int v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs(int x)
{
minn[x]=maxx[x]=id[x];
for(int i=head[x];i!=0;i=e[i].nxt)
{
dfs(e[i].to);
minn[x]=min(minn[x],minn[e[i].to]);
maxx[x]=max(maxx[x],maxx[e[i].to]);
}
}
void update(int n,int x,int key)
{
for(int i=x;i<=n;i+=lowbit(i))
{
c[i]+=key;
}
}
int getsum(int x)
{
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
{
ans+=c[i];
}
return ans;
}
int main()
{
int n,i,j,u,v,ans=0,flag;
cin>>n;
for(i=1;i<=n-1;i++)
{
cin>>u;
v=i+1;
add(u,v);
}
for(i=1;i<=n;i++)
{
cin>>p[i];
id[p[i]]=i;
}
dfs(1);
for(i=1;i<=n;i++)
{
update(n,minn[i],1);
update(n,maxx[i]-1+1,-1);
}
for(i=1;i<=n;i++)
{
cout<<getsum(i)<<" ";
}
return 0;
}
- 差分
struct node
{
int nxt,to;
}e[200001];
int head[200001],minn[200001],maxx[200001],p[200001],id[200001],sum[400001],cnt=0;
void add(int u,int v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs(int x)
{
minn[x]=maxx[x]=id[x];
for(int i=head[x];i!=0;i=e[i].nxt)
{
dfs(e[i].to);
minn[x]=min(minn[x],minn[e[i].to]);
maxx[x]=max(maxx[x],maxx[e[i].to]);
}
}
int main()
{
int n,i,j,u,v,ans=0;
cin>>n;
for(i=1;i<=n-1;i++)
{
cin>>u;
v=i+1;
add(u,v);
}
for(i=1;i<=n;i++)
{
cin>>p[i];
id[p[i]]=i;
}
dfs(1);
for(i=1;i<=n;i++)
{
sum[minn[i]]++;
sum[maxx[i]-1+1]--;
}
for(i=1;i<=n-1;i++)
{
ans+=sum[i];
cout<<ans<<" ";
}
cout<<"0";
return 0;
}
- 树状数组的区间修改单点查询操作
- 做法一:暴力跳父亲时跳到某个点时,若这个点既不是以这个点的父亲节点为根的子树内最先出现的黑点,也不是最后一个变成黑点的红点时就没有必要跳了,因为不会对答案产生贡献了(这里可能有些绕口,自己可以画图模拟一下)。
- 前置知识:红黑子树的产生与消失都是由改变颜色的这个点造成的。
\(T3\) 校门外的树 \(30pts\)
- 简化题意:门外有 \(n\) 棵树,每棵树有一个初始高度 \(h_i\) 和生长速度 \(v_i\) ,在接下来的 \(m\) 天中,第 \(i\) 棵树会长高 \(v_i\) ,之后有两种事件可能会发生,操作如下(对 \(2^{64}\) 取模):
- 操作一:将 \([l,r]\) 内树的生长速度 \(v_i(l \le i \le r)\) 增加 \(v\) 。
- 操作二:求 \(\sum\limits_{i=l}^{r} h_i\) 。
- 部分分:
- \(30pts\) : \(n^2\) 暴力枚举。
- \((30+20=50)pts\) :考虑到没有修改操作,维护一下即可。
- 正解:
简化版:若一个数 \(a\) ,有它的增长量 \(v\) ,在第 \(i\) 次操作时,有 \(a_{i}=a_{i-1}+v=a_1+i \times v\) 。
对 \(2^{64}\) 取模直接用 \(unsigned \ long \ long\) 自然溢出即可。
令 \(a_{i,j}\) 表示第 \(i\) 棵树第\(j\) 天的高度,特别地,有 \(a_{i,0}=h_i\) ,接着进行前缀和优化 \(sum_i=\sum\limits_{j=1}^{i} a_{j,0}(1 \le i,j \le n)\) 。
将操作二式子进行化简,有
\(\begin{aligned}\sum\limits_{i=l}^{r} a_{i,k} \end{aligned}\)
\(\begin{aligned} &=\sum\limits_{i=l}^{r} a_{i,0} \times k \times \sum\limits_{i=l}^{r} v_{i,num_i}-\sum\limits_{i=l}^{r}\sum\limits_{j=1}^{num_i}v_{i,j} \times day_{i,j} \end{aligned}\)
\(\begin{aligned} &= sum[r]-sum[l-1]+k \times \sum\limits_{i=l}^{r} v_{i,num_i}-\sum\limits_{i=l}^{r}\sum\limits_{j=1}^{num_i-1}(v_{i,j+1}-v_{i,j}) \times day_{i,j}\end{aligned}\) ,
其中 \(day_{i,j}\) 表示第 \(i\) 棵树第 \(j\) 次修改速度时是第几天,\(num_i\) 表示第 \(i\) 棵树生长速度修改的次数, \(k\) 表示本次是第 \(k\) 次操作。
考虑用线段树维护 \(\sum\limits_{i=l}^{r} v_{i,num_i}\) 和 \(\sum\limits_{i=l}^{r}\sum\limits_{j=1}^{num_i-1}(v_{i,j+1}-v_{i,j}) \times day_{i,j}\) ,将其 分别储存在两棵线段树 或存在一棵线段树中(其实差别不大)。
ull h[3000000],v[3000000],sum[3000000];
struct SegmentTree
{
ull l,r,sum[2],lazy[2];
}tree[3000000];
ull lson(ull x)
{
return x*2;
}
ull rson(ull x)
{
return x*2+1;
}
void pushup(ull rt,ull pd)
{
tree[rt].sum[pd]=tree[lson(rt)].sum[pd]+tree[rson(rt)].sum[pd];
}
void build(ull rt,ull l,ull r,ull pd)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].lazy[pd]=0;
if(l==r)
{
tree[rt].sum[pd]=v[l];
return;
}
ull mid=(l+r)/2;
build(lson(rt),l,mid,pd);
build(rson(rt),mid+1,r,pd);
pushup(rt,pd);
}
void pushdown(ull rt,ull pd)
{
if(tree[rt].lazy[pd]!=0)
{
tree[lson(rt)].lazy[pd]+=tree[rt].lazy[pd];
tree[rson(rt)].lazy[pd]+=tree[rt].lazy[pd];
tree[lson(rt)].sum[pd]+=tree[rt].lazy[pd]*(tree[lson(rt)].r-tree[lson(rt)].l+1);
tree[rson(rt)].sum[pd]+=tree[rt].lazy[pd]*(tree[rson(rt)].r-tree[rson(rt)].l+1);
tree[rt].lazy[pd]=0;
}
}
void update(ull rt,ull l,ull r,ull val,ull pd)
{
if(l<=tree[rt].r&&tree[rt].l<=r)
{
if(l<=tree[rt].l&&tree[rt].r<=r)
{
tree[rt].lazy[pd]+=val;
tree[rt].sum[pd]+=val*(tree[rt].r-tree[rt].l+1);
return;
}
pushdown(rt,pd);
update(lson(rt),l,r,val,pd);
update(rson(rt),l,r,val,pd);
pushup(rt,pd);
}
}
ull query(ull rt,ull l,ull r,ull pd)
{
if(r<tree[rt].l||tree[rt].r<l)
{
return 0;
}
if(l<=tree[rt].l&&tree[rt].r<=r)
{
return tree[rt].sum[pd];
}
pushdown(rt,pd);
return query(lson(rt),l,r,pd)+query(rson(rt),l,r,pd);
}
int main()
{
ull n,m,i,pd,l,r,v2;
cin>>n>>m;
for(i=1;i<=n;i++)
{
cin>>h[i]>>v[i];
sum[i]=sum[i-1]+h[i];
}
build(1,1,n,0);
for(i=1;i<=m;i++)
{
cin>>pd>>l>>r;
if(pd==1)
{
cin>>v2;
update(1,l,r,v2,0);
update(1,l,r,v2*i,1);
}
if(pd==2)
{
cout<<(sum[r]-sum[l-1])+i*query(1,l,r,0)-query(1,l,r,1)<<endl;
}
}
return 0;
}
隔壁有口胡李超线段树的做法,不是很懂。
还有口胡吉司机线段树的。
\(T4\) 种树 \(0pts\)
- 简化题意:约翰要带 \(n\) 只牛去参加 \(q\) 次集会里的展示活动(每次集会是相互独立的),这些牛可以是公牛,也可以是母牛。牛们要站成一排,但是公牛是好斗的,为了避免公牛闹出乱子,约翰决定第 \(i(1 \le i \le q)\) 次集会中第 \(x_i\) 头必须是母牛,且任意两只公牛之间至少要有 \(k_i-1\) 只母牛。请计算一共有多少种排队的方法,所有公牛可以看成是相同的,所有母牛也一样。答案对 \(998244353\) 取模。
- 弱化版:luogu P6191 Bulls And Cows S
- @xrlong 说和之前的 luogu T309085 [DILL AKOI R3 G] 风头 很像。
- 部分分:
- \(0pts\) :当 \(k=1\) 时,易知方案数为 \(2^{n-1}\) 。
- \(60pts\) :计数类型的 \(DP\) 。
- 对于第 \(j(1 \le j \le q)\) 次集会,令 \(f_i(0 \le i \le n)\) 表示第 \(i\) 头是母牛的方案数, \(g_i(0 \le i \le n)\) 表示第 \(i\) 头是公牛的方案数。由定义,有 \(f_0=g_0=0,f_1=1,g_1=\begin{cases}1 & x \ne 1 \\ 0 & x=1\end{cases}\) 。容易对于 \(2 \le i \le n\) ,有递推式 \(f_i=f_{i-1}+g_{i-1},g_i=\begin{cases}0 & x=i \\ 1 & x \ne i,i \le k \\ f_{i-k}+g_{i-k} & x \ne i,i>k \end{cases}\) 。
- \(f_n+g_n\) 即为所求。
- 单次时间复杂度为 \(O(n)\) 。
- \(hack\) 数据生成器如下。
int main()
{
srand(time(0));
cout<<100000<<" "<<100000<<endl;
for(int i=1;i<=100000;i++)
{
cout<<(rand()%100000+1)<<" "<<i<<endl;
}
}
ll f[100001],g[100001];
int main()
{
ll n,q,i,j,x,k;
cin>>n>>q;
for(i=1;i<=q;i++)
{
cin>>x>>k;
f[1]=1;
if(x!=1)
{
g[1]=1;
}
else
{
g[1]=0;
}
for(j=2;j<=n;j++)
{
f[j]=(f[j-1]+g[j-1])%998244353;
if(j==x)
{
g[j]=0;
}
else
{
if(j<=k)
{
g[j]=1;
}
else
{
g[j]=(f[j-k]+g[j-k])%998244353;
}
}
}
cout<<(f[n]+g[n])%998244353<<endl;
}
return 0;
}
- \(hack\) 数据生成器如下。
- \(100pts\) :组合。
- 依据容斥原理,有第 \(x\) 头是母牛的方案数 \(=\) 总方案数 \(-\) 第 \(x\) 头是公牛的方案数。
- 总方案数:设公牛有 \(j(0 \le i \le n)\) 头,
- 当 \(j=0\) 时,显然只有 \(1\) 种方案。
- 当 \(j \ne 0\) 时,需要固定 \((j-1)(k-1)\) 头母牛,等价于求 \(\sum\limits_{i=1}^{j+1}x_i=n-j-(j-1)(k-1)\) 的非负正整数解的数量,易知其数量为 \(\dbinom{n-j-(j-1)(k-1)+j+1-1}{j+1-1}\) 。
- 第 \(x\) 头是公牛的方案数:
- 第 \(x\) 头是公牛需要 \(x-k+1 \sim x-1,x+1 \sim x+k-1\) 是母牛。
- \(1 \sim x-k\) 的方案数:设公牛有 \(j(0 \le j \le x-k)\) 头,
- 当 \(j=0\) 时,显然只有 \(1\) 种方案。
- 当 \(j \ne 0\) 时,需要固定 \((j-1)(k-1)\) 头母牛,等价于求 \(\sum\limits_{i=1}^{j+1}x_i=x-k-j-(j-1)(k-1)\) 的非负正整数解的数量,易知其数量为 \(\dbinom{x-k-j-(j-1)(k-1)+j+1-1}{j+1-1}\) 。
- \(x+k \sim n\) 的方案数:设公牛有 \(j(0 \le j \le n-(x+k-1))\) 头,
- 当 \(j=0\) 时,显然只有 \(1\) 种方案。
- 当 \(j \ne 0\) 时,需要固定 \((j-1)(k-1)\) 头母牛,等价于求 \(\sum\limits_{i=1}^{j+1}x_i=n-(x+k-1)-j-(j-1)(k-1)\) 的非负正整数解的数量,易知其数量为 \(\dbinom{n-(x+k-1)-j-(j-1)(k-1)+j+1-1}{j+1-1}\) 。
- 总方案数:设公牛有 \(j(0 \le i \le n)\) 头,
- 求一下边界, \(\sum\limits_{j=0}^{\left\lfloor\dfrac{n+k-1}{k-1}\right\rfloor}\dbinom{n-j-(j-1)(k-1)+j+1-1}{j+1-1}-(\sum\limits_{j=0}^{\left\lfloor\dfrac{x-k+k-1}{k-1}\right\rfloor}\dbinom{x-k-j-(j-1)(k-1)+j+1-1}{j+1-1} \times \sum\limits_{j=0}^{\left\lfloor\dfrac{n-(x+k-1)+k-1}{k-1}\right\rfloor}\dbinom{n-(x+k-1)-j-(j-1)(k-1)+j+1-1}{j+1-1})\) 即为所求。
- 预处理时间复杂度为 \(O(n)\) ,单次时间复杂度为 \(O(\dfrac{n}{k})\) 。
- 学校数据太水了,导致此做法过了。
- 极限数据为 \(\dfrac{\dfrac{100000 \times (100000+1)}{2}}{2}\), \(hack\) 数据生成器如下。
int main()
{
cout<<100000<<" "<<100000<<endl;
for(int i=1;i<=100000;++i)
{
cout<<i<<" "<<2<<endl;
}
}
- 极限数据为 \(\dfrac{\dfrac{100000 \times (100000+1)}{2}}{2}\), \(hack\) 数据生成器如下。
ll jc[200001],inv[200001],jc_inv[200001];
ll C(ll n,ll m,ll p)
{
if(n>=m&&n>=0&&m>=0)
{
return (jc[n]*jc_inv[m]%p)*jc_inv[n-m]%p;
}
else
{
return 0;
}
}
ll qpow(ll a,ll b,ll p)
{
ll ans=1;
while(b>0)
{
if(b&1)
{
ans=ans*a%p;
}
b>>=1;
a=a*a%p;
}
return ans;
}
int main()
{
ll n,q,i,j,x,k,p=998244353,sum1,sum2,sum3;
cin>>n>>q;
inv[1]=1;
jc[0]=jc_inv[0]=jc[1]=jc_inv[1]=1;
for(i=2;i<=n;i++)
{
inv[i]=(p-p/i)*inv[p%i]%p;
jc[i]=jc[i-1]*i%p;
jc_inv[i]=jc_inv[i-1]*inv[i]%p;
}
for(i=1;i<=q;i++)
{
cin>>x>>k;
if(k==1)
{
cout<<qpow(2,n-1,p)<<endl;
}
else
{
sum1=sum2=sum3=1;
for(j=1;j<=(n+k-1)/(k-1);j++)
{
sum1=(sum1+C(n-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p;
}
for(j=1;j<=(x-k+k-1)/(k-1);j++)
{
sum2=(sum2+C(x-k-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p;
}
for(j=1;j<=(n-(x+k-1)+k-1)/(k-1);j++)
{
sum3=(sum3+C(n-(x+k-1)-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p;
}
cout<<(sum1-sum2*sum3%p+p)%p<<endl;
}
}
return 0;
}
- 学校数据太水了,导致此做法过了。
- 依据容斥原理,有第 \(x\) 头是母牛的方案数 \(=\) 总方案数 \(-\) 第 \(x\) 头是公牛的方案数。
- 正解
- 根号分治
@wkh2008 瑞平 \(T4\) :
当 \(k> \sqrt{n}\) 时,考虑到组合做法难以进行进一步预处理,故使用组合做法。
当 \(k \le \sqrt{n}\) 时,考虑到对计数类型的 \(DP\) 做法利用容斥原理进一步预处理。对于第 \(j(1 \le j \le q)\) 次集会,令 \(f_i(0 \le i \le n)\) 表示第 \(i\) 头是母牛的方案数, \(g_i(0 \le i \le n)\) 表示第 \(i\) 头是公牛的方案数。由定义,有 \(f_{0,k}=g_{0,k}=0,f_{1,k}=g_{1,k}=1\) 。容易对于 \(2 \le i \le n\) ,有递推式 \(f_{i,k}=f_{i-1,k}+g_{i-1,k},g_{i,k}=\begin{cases} 1 & i \le k \\ f_{i-k,k}+g_{i-k,k} & i>k \end{cases}\) 。最终, \(f_{n,k}+g_{n,k}-(f_{\max(x-k,0),k}+g_{\max(x-k,0),k}) \times (f_{\max(n-(x+k-1),0),k}+g_{\max(n-(x+k-1),0),k})\) 即为所求。
- 本质上是对重复出现的 \(k\) 进行预处理。
空间复杂度为 \(O(n \sqrt{n})\) ;预处理时间复杂度为 \(O(n \sqrt{n})\) ,单次查询时间复杂度为 \(O(\sqrt{n})\) 。
ll jc[100001],inv[100001],jc_inv[100001],f[100001][320],g[100001][20],vis[20];
ll C(ll n,ll m,ll p)
{
if(n>=m&&n>=0&&m>=0)
{
return (jc[n]*jc_inv[m]%p)*jc_inv[n-m]%p;
}
else
{
return 0;
}
}
int main()
{
ll n,q,i,j,x,k,p=998244353,sum1,sum2,sum3;
cin>>n>>q;
inv[1]=1;
jc[0]=jc_inv[0]=jc[1]=jc_inv[1]=1;
for(i=2;i<=n;i++)
{
inv[i]=(p-p/i)*inv[p%i]%p;
jc[i]=jc[i-1]*i%p;
jc_inv[i]=jc_inv[i-1]*inv[i]%p;
}
for(i=1;i<=q;i++)
{
cin>>x>>k;
if(k<=20)
{
if(vis[k]==0)
{
vis[k]=1;
f[1][k]=g[1][k]=1;
for(j=2;j<=n;j++)
{
f[j][k]=(f[j-1][k]+g[j-1][k])%p;
if(j<=k)
{
g[j][k]=1;
}
else
{
g[j][k]=(f[j-k][k]+g[j-k][k])%p;
}
}
}
sum1=(f[n][k]+g[n][k])%p;
sum2=(f[max(x-k,0ll)][k]+g[max(x-k,0ll)][k])%p;
sum3=(f[max(n-(x+k-1),0ll)][k]+g[max(n-(x+k-1),0ll)][k])%p;
}
else
{
sum1=sum2=sum3=1;
for(j=1;j<=(n+k-1)/(k-1);j++)
{
sum1=(sum1+C(n-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p;
}
for(j=1;j<=(x-k+k-1)/(k-1);j++)
{
sum2=(sum2+C(x-k-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p;
}
for(j=1;j<=(n-(x+k-1)+k-1)/(k-1);j++)
{
sum3=(sum3+C(n-(x+k-1)-j-(j-1)*(k-1)+j+1-1,j+1-1,p))%p;
}
}
cout<<(sum1-max(sum2,1ll)*max(sum3,1ll)%p+p)%p<<endl;
}
return 0;
}
- 根号分治
总结
- \(T1,T3,T4\) 打到 \(8:30,9:30\) 打完 \(T2\) 后就去打高斯消元了,导致没有看见 \(T3\) 的对 \(2^{64}\) 取模(打成了 \(2^{60}\) ),挂了 \(30pts\) 。
- \(T3\) 觉得线段树可做,但不想打了。
- \(T4\) 没有再多想想,没骗到计数类型的 \(DP\) 分。推式子的时候应注意更加模块化,防止因为推式子多推一步而导致无法得到正确式子。
2023年多校联训NOIP层测试7+【LGR-149-Div.3】洛谷基础赛 #2 & qw Round -1的更多相关文章
- Contest1893 - 2019年6月多校联训b层测试1
传送门 密码:waxadyt T1 暴力 对于任意相邻的两个值 中间能到达的最大高度是固定的 加上头尾,判一下就好了 代码//感谢Th Au K #include<bits/stdc++.h&g ...
- 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)
2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...
- 「题解」NOIP模拟测试题解乱写II(36)
毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...
- 2019.8.3 NOIP模拟测试12 反思总结【P3938 斐波那契,P3939 数颜色,P3940 分组】
[题解在下面] 早上5:50,Gekoo同学来到机房并表态:“打暴力,打暴力就对了,打出来我就赢了.” 我:深以为然. (这是个伏笔) 据说hzoi的人还差两次考试[现在是一次了]就要重新分配机房,不 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组
2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色
2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...
- NOIP模拟测试17&18
NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...
- 洛谷模拟NOIP考试反思
洛谷模拟NOIP考试反思 想法 考了这么简单的试qwq然而依然emmmmmm成绩不好 虽然本次难度应该是大于正常PJ难度的但还是很不理想,离预估分数差很多qwq 于是就有了本反思嘤嘤嘤 比赛链接 原比 ...
- 洛谷NOIp热身赛题解
洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ...
- [NOIP提高&洛谷P1024]一元三次方程求解 题解(二分答案)
[NOIP提高&洛谷P1024]一元三次方程求解 Description 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约 ...
随机推荐
- vmware超融合基础安装与配置
目录 vmware超融合 安装配置ESXI 安装VMware vCenter Server 安装vCenter插件 安装vCenter 使用VMware Vsphere Client登录Vcenter ...
- wiremock设置接口入参的判断条件
一.wiremock管理台url: http://192.168.37.8:7777/__admin/swagger-ui/ 可重启测试桩,获取响应信息等操作 二.设置接口响应入参的判断条件 如当影 ...
- 08-Shell计算命令
1.expr命令 expr (evaluate expressions 的缩写),译为"表达式求值".Shell expr 是一个功能强大,并且比较复杂的命令,它除了可以实现整数计 ...
- 【C++】const 常类型
常引用 格式:const 类型说明符 &引用名 注意:常引用所引用的对象不能修改 常对象 格式:类名 const 对象名 或 const 类名 对象名 注意:常对象其数据成员在生存期内不能修改 ...
- MongoDB 部署分片集群
部署配置服务器:configsvr 先生成.conf文件 mkdir -p /data/mongodb/configsvr vim /data/mongodb/configsvr/configsvr. ...
- android应用申请加入电池优化白名单
首先,在 AndroidManifest.xml 文件中配置一下权限: 1 <uses-permission android:name="android.permission.REQU ...
- [粘贴]TiFlash
TiFlash 是 TiDB HTAP 形态的关键组件,它是 TiKV 的列存扩展,在提供了良好的隔离性的同时,也兼顾了强一致性.列存副本通过 Raft Learner 协议异步复制,但是在读取的时候 ...
- [转帖]Linux中find命令使用示例
https://zhuanlan.zhihu.com/p/99170116 Linux查找命令是类Unix操作系统中最重要且最常用的命令行实用程序之一. 查找命令可以根据你设定的参数匹配的文件指定的条 ...
- DPText-DETR: 基于动态点query的场景文本检测,更高更快更鲁棒 | 京东探索研究院
针对场景文本检测任务,近期基于DEtection TRansformer (DETR) 框架预测控制点的研究工作较为活跃.在基于DETR的检测器中,query的构建方式至关重要,现有方法中较为粗糙的位 ...
- 从零开始配置vim(28)——代码的编译、运行与调试
在前面几个章节,我们逐渐为 Vim 配置了语法高亮.代码的跳转和自动补全功能.现在的 Vim 已经可以作为代码编辑器来使用了.但是想将它作为日常发开的主力编辑器来用还需要很长一段路要走,其中一个就是要 ...