首页 > 其他分享 >CSP 模拟 3

CSP 模拟 3

时间:2024-07-25 14:10:03浏览次数:18  
标签:std typedef ch int sum long CSP 模拟

joke3579场,

T1 abc猜想 ([ARC111A] Simple Math 2)

直接 \(\bmod \ c\),很难做,不难想到换一个和 \(c\) 有关的模数,\(c^2\) 很好,因为它除以 \(c\) 再模上 \(c\) 后为 \(0\)。
求 \(x=a^b(\bmod\ c^2)\),\(a^b=k\cdot c^2+x\),除以 \(c\) 模 \(c\) 后,前面那个东西没了,只剩 \(x\),所以答案就是 \(\left\lfloor\frac{x}{c}\right\rfloor\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
typedef long long ll;
typedef unsigned long long ull;
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=1e4+10;
const int MOD=1e9+7;
std::vector<int> sth;
inline int qpow(int a,int b,int mod){
	int res=1;
	for(;b;b>>=1,a=a*a%mod)if(b&1)res=res*a%mod;
	return res;
}
bool vis[N];
signed main(){
	// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
	std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
	int a=read(),b=read(),c=read();
	int qc=c*c;
	int ans=qpow(a,b,qc);
	std::cout<<ans/c<<'\n';
}

T2 简单的排列最优化题 (CF819B Mister B and PR Shifts)

很容易的想到 \(n^2\) 做法,发现有很多东西都是重复记录了。考虑继承这些东西。
定义一个位置的价值为 \(a_i-i\),然后记一下这个价值出现的次数,发现每右移一位,这些价值的数量都会左移一位,即原来价值为 \(x\) 的现在价值为 \(x-1\)。
同时,答案可以借助这些价值从上一次的答案转移过来,即价值为非正整数的会对答案做出 \(1\) 的贡献,价值为正整数的做出 \(-1\) 的贡献。
此时只需要支持单点修改区间查询即可,树状数组是个不错的选择(其实再记一下其他东西可以 \(\mathcal{O}(n)\),不过 ds 不要脑子)。
对于每次的右移,开个变量记录一下就行,对于末尾的点单独算。

点击查看代码
#include<bits/stdc++.h>
#define int long long
typedef long long ll;
typedef unsigned long long ull;
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=4e6+10;
int t[N],len,n,a[N],last,ans=0,mink,minans;
inline void add(int pos,int x){int zc=pos+1;for(;pos<=len;pos+=pos&-pos)t[pos]+=x;}
inline int query(int l,int r){
	int res=0;
	l--;
	for(;l;l-=l&-l)res-=t[l];
    for(;r;r-=r&-r)res+=t[r];
	return res;
}
inline int real(int x){return x+n+last;}
signed main(){
	// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
	std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
	n=read();len=n*4+1;
	for(int i=1;i<=n;++i){
		a[i]=read();
		add(real(a[i]-i),1);ans+=std::abs(a[i]-i);
	}
	mink=0,minans=ans;
	for(int i=1;i<=n-1;++i){
		int en=a[n-i+1];
		add(real(en-n),-1);
		ans+=-(std::abs(en-n))+en-1+query(1,real(0))-query(real(1),real(n-1));
		if(minans>ans){minans=ans,mink=i;}
		last++;
		add(real(en-1),1);
	}
	std::cout<<minans<<' '<<mink<<'\n';
}

T3 简单的线性做法题 (P4062 [Code+#1] Yazid 的新生舞会)

感觉是妙妙题,有较多做法,甚至有线性。这里介绍树状数组处理三阶前缀和的做法。
考虑对每个数单独处理。设 \(f_i\) 表示这个数到 \(i\) 位置时出现的次数,对于合法区间 \((l,r]\),\(f_r-f_l>\frac{r-l}{2}\Leftrightarrow 2f_r-r>2f_l-l\),直接拿树状数组维护 \(2f_i-i\) 的话,时间复杂度 \(\mathcal{O}(n^2\log n)\) 的。观察性质,发现对于每个数,它的 \(2f_i-i\) 是可以分段的。
image
简单观察发现,在两个相同数之间,它的 \(2f_i-i\) 是递减的,然后加一,然后又递减,而这些段的数量是 \(\mathcal{O}(n)\) 的,这启示我们去维护这些段。对于 \(a_i=2f_i-i\),要去前面找比他小的,\(T_i=\sum_{j=1}^i a_i\),\(W_i=\sum_{j=1}^i Ti\),树状数组上差分,设 \(d\) 为 \(a\) 的差分数组,有 \(a_i=\sum_{j=1}^i\)

\[\begin{aligned} W_n&=\sum_{i=1}^n\sum_{j=1}^i\sum_{k=1}^j d_j\\ &=\sum_{i=1}^n\sum_{j=1}^i (i-j+1)d_j\\ &=\sum_{i=1}^n\frac{(n-i+2)(n-i+1)}{2}d_i\\ &=\frac{(n+1)(n+2)}{2}\sum_{i=1}^n d_i-n\sum_{i=1}^n i\cdot d_i+\frac{1}{2}\sum_{i=1}^n i(i-3)d_i \end{aligned} \]

开三个树状数组分别维护一下就好了,具体看代码。

点击查看代码
#include<bits/stdc++.h>
#define int long long
typedef long long ll;
typedef unsigned long long ull;
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=1e6+10;
int n,a[N],d[N],c,temp[N],ans,t1[N],t2[N],t3[N];
std::vector<int> p[N];
inline void add(int l,int r,int x){
	if(l>r)return;
	l+=n+1,r+=n+1;r++;
	for(int i=l;i<=2*n+1;i+=i&-i)t1[i]+=x,t2[i]+=l*x,t3[i]+=(l*l-3*l)*x;
	for(int i=r;i<=2*n+1;i+=i&-i)t1[i]-=x,t2[i]-=r*x,t3[i]-=(r*r-3*r)*x;
}
inline int query(int l,int r){
	if(l>r)return 0;
	int res1=0,res2=0;
	l+=n+1,r+=n+1;l--;
	for(int i=r;i;i-=i&-i)res1+=(((r+1)*(r+2))>>1)*t1[i]-r*t2[i]+t3[i]/2;
	for(int i=l;i;i-=i&-i)res2+=(((l+1)*(l+2))>>1)*t1[i]-l*t2[i]+t3[i]/2;
	return res1-res2;
}
inline void work(int x){
	int num=0,last=0;
	for(int i:p[x]){
		num++;
		int zc=num*2-i;
		int l=zc-1,r=zc-1+i-1-last;
		ans+=query(l-1,r-1);
		add(l,r,1);
		last=i;
	}
	int zc=num*2-n;
	int l=zc,r=l+n-last;
	ans+=query(l-1,r-1);
	num=0;last=0;
	for(int i:p[x]){
		num++;
		int zc=num*2-i;
		int l=zc-1,r=zc-1+i-1-last;
		add(l,r,-1);
		last=i;
	}
}
signed main(){
	// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
	std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
	n=read();
	for(int i=1;i<=n;++i){temp[i]=a[i]=read();}
	std::sort(temp+1,temp+1+n);
	int len=std::unique(temp+1,temp+1+n)-temp-1;
	for(int i=1;i<=n;++i)a[i]=std::lower_bound(temp+1,temp+1+len,a[i])-temp,p[a[i]].push_back(i);;
	for(int i=1;i<=len;++i)work(i);
	std::cout<<ans<<'\n';
}

T4 简单的线段树题

原题 P4145 上帝造题的七分钟 2 / 花神游历各国
这题太典了,开方到 \(1\) 后就没啥意义了,并且开不了多少次,直接魔改线段树维护即可。

点击查看代码
#include<bits/stdc++.h>
#define int long long
typedef long long ll;
typedef unsigned long long ull;
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=1e6+10;
int a[N],n,m;
struct TREE{int num,sum;}t[N<<2];
inline void update(int p){
	t[p].num=t[p<<1].num+t[p<<1|1].num;
	t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
}
inline void build(int p,int l,int r){
	if(l==r){t[p]={a[l]==1?1:0,a[l]};return;}
	int mid=l+r>>1;
	build(p<<1,l,mid);build(p<<1|1,mid+1,r);
	update(p);
}
inline void modi(int p,int l,int r,int x,int y){
	if(l>=x&&r<=y){
		if(t[p].num==r-l+1){return;}
		int mid=l+r>>1;
		if(l==r){t[p].sum=std::sqrt(t[p].sum);t[p].num=(t[p].sum==1?1:0);return;}
		if(t[p<<1].num<mid-l+1)modi(p<<1,l,mid,x,y);
		if(t[p<<1|1].num<r-mid)modi(p<<1|1,mid+1,r,x,y);
		update(p);
		return;
	}
	int mid=l+r>>1;
	if(x<=mid)modi(p<<1,l,mid,x,y);
	if(y>mid)modi(p<<1|1,mid+1,r,x,y);
	update(p);
}
inline int query(int p,int l,int r,int x,int y){
	if(l>=x&&r<=y)return t[p].sum;
	int mid=l+r>>1,res=0;
	if(x<=mid)res+=query(p<<1,l,mid,x,y);
	if(y>mid)res+=query(p<<1|1,mid+1,r,x,y);
	return res;
}
signed main(){
	// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
	std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
	n=read();
	for(int i=1;i<=n;++i)a[i]=read();
	build(1,1,n);
	m=read();
	for(int i=1;i<=m;++i){
		int op=read(),l=read(),r=read();
		if(op){std::cout<<query(1,1,n,l,r)<<'\n';}
		else modi(1,1,n,l,r);
	}
}

标签:std,typedef,ch,int,sum,long,CSP,模拟
From: https://www.cnblogs.com/Ishar-zdl/p/18313847

相关文章

  • eve-NG网络环境模拟神器
    一个看着很像计网实验的一个万能模拟工具。下载https://www.eve-ng.net/index.php/download/安装导入eve镜像之前需要安装一些软件。SecureCRT:用来连接telnet的MobaXterm:类似xshell的工具EVE-NG-Win-Client-Pack-2.0:主要是用于Wireshark抓包直接去官网下载即可https://e......
  • can环境模拟+重放攻击+逆向分析
    安装ICSimsudoaptinstalllibsdl2-devlibsdl2-image-devcan-utilsmavenautoconf-y#下载ICSimgitclonehttps://github.com/zombieCraig/ICSim.git#编译安装cdICSim/sudomake安装socketcand#下载socketcandgitclonehttps://github.com/linux-can/socket......
  • ccfcsp 201803.2 碰撞的小球 100分代码
    本题是一道小模拟规模小难度在碰撞检测在写模拟题时的思路应该是先找到应该储存的信息是哪些,抽象出来,应该模拟的方法是哪些。类似oop。includeusingnamespacestd;constintL=1000;structball{intp;chard=1;//只可能为1或-1,表示方向}b[L+1];intmain(){int......
  • YC322A [ 20240724 CQYC NOIP 模拟赛 T4 ] 庫的 序计数(counting)
    题意给定一棵树\(T\),每次操作在某个点下方接上\(k\)个儿子。询问期望多少次排列,使得\(a_{fa_i}<a_i\)。保证\(k\)是偶数,对\(65536\)取模。\(n\le10^5,k\le2\times10^9\)。Sol考虑假如已经确定了一棵树的形态,如何求出最终的答案?可以发现对于每一个节点......
  • 「模拟赛」暑期集训CSP提高模拟4(7.21)
    很祭的一次比赛,啥也不会。题目列表:A.WhiteandBlackB.WhiteandWhiteC.BlackandBlackD.BlackandWhiteA.WhiteandBlack\(0pts\)题意:给你一颗树,树根为1,初始所有点都是白色,每次询问给出一个点集,若把点集中的点全部染成黑色,问至少需要翻转多少个节点才能使整......
  • 2024.7.22模拟赛5
    模拟赛咕了两天才发现少了一天的题解。T1MakeItIncreasing水。code#include<bits/stdc++.h>usingnamespacestd;constintN=40;#defineLLlonglongintt,n;LLa[N];intmain(){// freopen("in.in","r",stdin);// freopen("out.out",&......
  • 暑假集训CSP提高模拟6
    赛时在\(T2\)浪费时间太多,导致\(T4\)暴力没时间想了,总是想把\(T2\)这种题当大型分讨来做A.花间叔祖[ARC148A]modM观察性质可以发现,答案要么是1,要么是2,把是1的情况找出来剩下的就是2。考虑什么时候是1,如果一个数列模上一个数结果相同,那么他们的差一定是这个模数的整......
  • 暑假集训CSP提高模拟3
    暑假集训CSP提高模拟32/35反向挂了若干分又正向挂了若干T1abc猜想水,随便变形推个柿子糊个快速幂就好了T2简单的排列最优化题考虑只计算每次右移的\(delta\),我们发现一个点只会在到贡献为\(0\)的位置和序列开头会改变对\(delta\)的贡献,直接算就好,\(O(n)\)的T3简单......
  • [题解]P9755 [CSP-S 2023] 种树
    P9755[CSP-S2023]种树迟来的补题本题是让最小化所有树长到指定高度日期的最大值,于是想到二分答案。那么,对于一个给定的期限\(x\),如何判断是否能在这个日期内完成任务呢?首先我们发现前\(n\)天每天都要种树,那么假设我们已经知道了每个地块最晚哪个日期种树,能保证在期限\(x\)......
  • 20240724【省选】模拟
    挂了四分,掉了一名,不过这也说明我的实力就只有这点,根本不够,果然以后还是直接【数据删除】得了。T1其实就是个树剖,每个点维护左右子树的最大深度以及左右子树内的最大答案,然后就…………没了?淦,也是实现问题,应该想到的。然后就是修改边权是改成\(w-a_p\),\(a_i\)是记录下来的\(i......