2023.3.15 日寄
2023.3.15 日寄
杂题专训
Mergesort Strikes Back
题意
记 为归并的第 层,求对一个排列归并排序只执行到第 层,操作完成后逆序对个数的期望。对一个大质数取模。
.
题解
非常厉害的题目啊。(指很多性质
首先是 合并排序(指没有进行递归)时候的结论:按照前缀最大值相同的数分为一块(如果归并有分块那以归并的分块来),那么此时排序就是将每个块的第一位从小到大排序。这个是 abracadabra 的套路。
然后考虑对于每个初始的长为 的块,显然其内部的顺序不会再变,所以内部的数对 个都有 的概率贡献,也就是 的期望贡献。
对于两个长度分别为 和 的块,我们考虑其贡献的数对任何一个位置都必然不可能来自首位(首位是已经排过序的,并且由于首位是前缀最大值,不可能后面的位置有机会) 。那么也就是 的概率找到数对,然后还是 的概率贡献。把这个式子拆开前缀和维护一下就好了。
代码
查看代码
#include <bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define mp(a,b) make_pair(a,b)
using namespace std;
template<typename T>void read(T &x)
{
T f=1;x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
x*=f;
}
int n,k,MOD;
inline int Add(int a,int b){return (a+b)%MOD;}
inline int Dec(int a,int b){return (a-b+MOD)%MOD;}
inline int Mul(int a,int b){return 1ll*a*b%MOD;}
inline int qpow(int a,int b)
{
int ret=1;
while(b)
{
if(b&1) ret=Mul(ret,a);
b>>=1;a=Mul(a,a);
}
return ret;
}
int buc[200005];
void Merge(int l,int r,int dep)
{
if(dep==k||l==r){buc[r-l+1]++;return;}
int mid=(l+r)>>1;
Merge(l,mid,dep+1); Merge(mid+1,r,dep+1);
}
vector <int> Len;
int Pre[200005],Inv2,Inv4;
inline ll Calc(int x,int y)
{
ll ret=Mul(Mul(x,y),Inv2);
for(int i=1;i<=x;i++) ret=Dec(ret,Dec(Pre[i+y],Pre[i]));
return ret;
}
int main() {
read(n);read(k);read(MOD);
Inv2=qpow(2,MOD-2); Inv4=qpow(4,MOD-2);
for(int i=1;i<=100000;i++) Pre[i]=Add(Pre[i-1],qpow(i,MOD-2));
Merge(1,n,1);
for(int i=1;i<=n;i++) if(buc[i]) Len.push_back(i);
ll Ans=0;
for(int i=0;i<(int)Len.size();i++)
{
int L=Len[i];
Ans=Add(Ans,Mul(buc[L],Mul(Mul(L,L-1),Inv4)));
Ans=Add(Ans,Mul(Mul(Mul(buc[L],buc[L]-1),Inv2),Calc(L,L)));
}
for(int i=0;i<(int)Len.size();i++)
{
int L1=Len[i];
for(int j=i+1;j<(int)Len.size();j++)
{
int L2=Len[j];
Ans=Add(Ans,Mul(Mul(buc[L1],buc[L2]),Calc(L1,L2)));
}
}
printf("%lld",Ans);
return 0;
}
/*
瑶草一何碧,春入武陵溪。溪上桃花无数,花上有黄鹂。我欲穿花寻路,直入白云深处,浩气展虹霓。只恐花深里,红露湿人衣。
坐玉石,欹玉枕。拂金徽。谪仙何处,无人伴我白螺杯。我为灵芝仙草,不为朱唇丹脸,长啸亦何为。醉舞下山去,明月逐人归。
*/
「LibreOJ β Round #4」求和
题意
给定正整数 ,求 对 取模的结果.
.
题解
套路性地先枚举 :
然后套路莫反:
然后丢个结论:
证明:
考虑 的质因子指数都 ,不然必然为 .
若 ,那么:
那么你整除分块或者直接枚举 的值都是 的做法,做就完了。这个trick可以记下来。
代码
查看代码
#include <bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define mp(a,b) make_pair(a,b)
using namespace std;
template<typename T>void read(T &x)
{
T f=1;x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
x*=f;
}
int Prime[4000005],tot;
int mu[4000005],vis[4000005];
void Init(int N)
{
mu[1]=1;
for(int i=2;i<=N;i++)
{
if(!vis[i]) {mu[i]=-1;Prime[++tot]=i;}
for(int j=1;j<=tot&&i*Prime[j]<=N;j++)
{
vis[i*Prime[j]]=1;
if(i%Prime[j]) mu[i*Prime[j]]=-mu[i];
else break;
}
}
for(int i=1;i<=N;i++) mu[i]+=mu[i-1];
}
const ll MOD=998244353;
inline ll Add(ll a,ll b){a%=MOD;b%=MOD;a+=b;return a>=MOD?a-MOD:a;}
inline ll Dec(ll a,ll b){a%=MOD;b%=MOD;a-=b;return a<0?a+MOD:a;}
inline ll Mul(ll a,ll b){a%=MOD;b%=MOD;return 1ll*a*b%MOD;}
inline ll qpow(ll a,ll b)
{
ll ret=1;
while(b)
{
if(b&1) ret=Mul(ret,a);
b>>=1;a=Mul(a,a);
}
return ret;
}
int main() {
Init(4000000);
ll n,m,Ans=0;read(n);read(m);
for(ll l=1,r;l<=n&&l<=m;l=r+1)
{
r=min(n/(n/l),m/(m/l));
ll L=ceil(sqrt(l)),R=floor(sqrt(r));
Ans=Add(Ans,Mul(Mul(n/l,m/l),Dec(mu[R],mu[L-1])));
}
printf("%lld",Ans);
return 0;
}
/*
瑶草一何碧,春入武陵溪。溪上桃花无数,花上有黄鹂。我欲穿花寻路,直入白云深处,浩气展虹霓。只恐花深里,红露湿人衣。
坐玉石,欹玉枕。拂金徽。谪仙何处,无人伴我白螺杯。我为灵芝仙草,不为朱唇丹脸,长啸亦何为。醉舞下山去,明月逐人归。
*/
「AGC018C」 Coins
题意
有 个人,每个人有三个属性 ,要求选择 个人属性为 , 个人属性为 , 个人属性为 ,最终他们的和最大。求这个最大的和。
.
题解
有一个显然的费用流建模,看看数据范围,果断模拟费用流开始反贪。
考虑先得到一组解,不妨就令前 个人取 ,中间 个人取 ,最后 个人取 .那么我们考虑每次替换找新的方案。记 表示把一个本来取 的变为 。以此类推,那我们就有以下五种交换方案:
- ;
- ;
- ;
- ;
- 。
每种都选那个交换过后能获取最大 的人,选择这五种当中最大的那一个反悔贪心即可。显然任何时候得到的解都是合法的。
代码
查看代码
#include <bits/stdc++.h>
#define ll long long
#define PII pair<ll,ll>
#define mp(a,b) make_pair(a,b)
using namespace std;
template<typename T>void read(T &x)
{
T f=1;x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
x*=f;
}
ll Ans;
int Type[100005];
int a[100005][3];
struct cmp {
bool operator()(const PII x,const PII y){return x.first!=y.first?x.first<y.first:x.second<y.second;}
};
priority_queue<PII,vector<PII>,cmp>Q[10];
void Add(int i)
{
for(int j=0;j<=8;j++)
{
int x=j/3,y=j%3;
if(x==y) continue;
Q[j].push(mp(a[i][x]-a[i][y],i));
}
}
int main() {
int x,y,z,n;read(x);read(y);read(z); n=x+y+z;
for(int i=1;i<=n;i++) read(a[i][0]),read(a[i][1]),read(a[i][2]),Add(i);
for(int i=1;i<=x;i++) Ans+=a[i][0],Type[i]=0;
for(int i=x+1;i<=x+y;i++) Ans+=a[i][1],Type[i]=1;
for(int i=x+y+1;i<=n;i++) Ans+=a[i][2],Type[i]=2;
while("I am an idiot.")
{
for(int i=0;i<=8;i++)
{
int X=i/3,Y=i%3;
if(X==Y) continue;
while(!Q[i].empty()&&Type[Q[i].top().second]!=Y) Q[i].pop();
}
ll Val[9];
for(int i=0;i<=8;i++)
{
if(!Q[i].empty()) Val[i]=Q[i].top().first;
else Val[i]=-1e17;
}
ll Maxn=0,pos;
/*五个环*/
if(Val[3]+Val[7]+Val[2]>Maxn) Maxn=Val[3]+Val[7]+Val[2],pos=1;
if(Val[6]+Val[5]+Val[1]>Maxn) Maxn=Val[6]+Val[5]+Val[1],pos=2;
if(Val[3]+Val[1]>Maxn) Maxn=Val[3]+Val[1],pos=3;
if(Val[6]+Val[2]>Maxn) Maxn=Val[6]+Val[2],pos=4;
if(Val[7]+Val[5]>Maxn) Maxn=Val[7]+Val[5],pos=5;
if(Maxn==0) break; Ans+=Maxn;
int x,y,z;
if(pos==1) Type[x=Q[3].top().second]=1,Type[y=Q[7].top().second]=2,Type[z=Q[2].top().second]=0,Add(x),Add(y),Add(z);
if(pos==2) Type[x=Q[6].top().second]=2,Type[y=Q[5].top().second]=1,Type[z=Q[1].top().second]=0,Add(x),Add(y),Add(z);
if(pos==3) Type[x=Q[3].top().second]=1,Type[y=Q[1].top().second]=0,Add(x),Add(y);
if(pos==4) Type[x=Q[6].top().second]=2,Type[y=Q[2].top().second]=0,Add(x),Add(y);
if(pos==5) Type[x=Q[7].top().second]=2,Type[y=Q[5].top().second]=1,Add(x),Add(y);
}
printf("%lld",Ans);
return 0;
}
/*
瑶草一何碧,春入武陵溪。溪上桃花无数,花上有黄鹂。我欲穿花寻路,直入白云深处,浩气展虹霓。只恐花深里,红露湿人衣。
坐玉石,欹玉枕。拂金徽。谪仙何处,无人伴我白螺杯。我为灵芝仙草,不为朱唇丹脸,长啸亦何为。醉舞下山去,明月逐人归。
From 0 1 2
To
0 / 1 2
1 3 / 5
2 6 7 /
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现