Akane-Weekly #2NOIP 十连测 (2)

Akane-Weekly #2:NOIP 十连测 (2)

今日得分:40+35+0+80=155,完全寄了

C.

神仙题。

简要题意:

给你一个正整数 \(x\) 和一个质数 \(p\) ,让你找三个正整数 \(a,b,c\) ,满足 \(ab+bc+ca=xp^2\) ,或者报告无解。

Solution:

首先,我们可以将 \(ab+bc+ca\) 转化为 \((a+b)(a+c)-a^2\)

所以我们有 \((a+b)(a+c)=xp^2+a^2\)

很直接想到试一下 \(a=p\) ,发现可以凑出 \(a=p,b=x+1-p,c=p^2-p\)

发现只有当 \(x+1-p>0\) 是可以成立,固这一类子问题已经解决。

\(p>x+1\) 的时候,我们可以类似地解决,令 \(p=k+(x+1)b(0<k\le x)\)

我们让 \(a=k\) ,代入推一下式子,可以得到 \(b=x+1-k\)

\[c=k^2+bx[(x+1)b+2k]-k \]

发现 \(b,c\) 显然大于 \(0\) ,只需要满足 \(a>0\) 即可。

\(a=0\) 时,发现 \(b=1\) ,不然 \(p\) 就不是质数了。

所以我们最后需要考虑一下 \(x=k+1\) 的情况。

我们化简式子得到

\[p^3+p^2+a^2=(a+b)(a+c) \]

待定系数,令 \(p^3+p^2+a^2=(p^2+yp+z)(p+u)\)

考虑到 \(zu\) 是完全平方数, \(z+yu=0\) 可以得到 \(-y\) 是完全平方数,枚举一下发现当 \(y=-4,u=3,z=12\) 时可以,所以有 \(a=6,b=p-3,c=p^2-4p+6\)

当然 \(p<=3\) 时不适用,手玩一下 \(x=1,p=2\)\(x=2,p=3\) 的情况,发现均无解。

Code:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
signed main(){
//	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t,x,p,a,b,c,k,by;
	t=read();
	while(t--){
		x=read(),p=read();
		if(x+1==p){
			a=6,b=p-3,c=p*p-4*p+6;
		}else{
			a=k=p%(x+1);
			by=p/(x+1);
			b=x+1-a;
			c=k*k+by*x*((x+1)*by+2*k)-a;
		}
		if((x==2&&p==3)||(x==1&&p==2)) printf("-1\n");	
		else printf("%lld %lld %lld\n",a,b,c);
	}
}

B.

简要题意:

对于每一个个体,有一下五种操作:

1.向前走一步。

2.向后走一步,如果有标记且向后走之后位置小于标记,那么删除标记。

3.在当前位置打一个标记,一个个体只保留位置最小的标记。

4.走到标记处并清空标记,如果没有标记则不动。

5.询问这个个体的位置。

现在有 \(n\) 个个体,同时把操作 \(1-4\) 改成区间操作。

每个个体的初始位置均为 \(5e5\) ,且保证操作种类随机。

\(n,q\le5e5\)

Solution:

显然要用线段树维护,但问题在于怎么写。

考虑随机性,我们可以用二进制暴力维护每个个体每一位是否有标记的状态,如果要清空标记就清空数组重新开始,如果要后退就缩掉最后一位,搞一个 \(long long\) 数组维护,叫作 \(abj\)

维护每个个体的位置数字 \(a\) ,但它不用上推,只有当上面有要对 \(a\) 修改的时候进行下推即可。

维护一个 \(bool\) 数组 \(flg\) ,表示区间是否有个体打上了标记,方便在操作 \(4\) 线段树上下推的时候判断终止,这个要 \(pushup\) 维护。

还有两个数组 \(fgl,fgr\) ,前者记录 \(abj\) 的位数,即已经往前走未回溯的步数,方便回退的时候减掉,如果要减的比 \(fgl\) 多,就记在 \(fgr\) 里面,当做懒标记下推即可。

操作 \(4\) 的时候即使找到了包含区间也要继续推来清除 \(flg\) ,不过由于随机性,时间也可以保证,(能过就可以了

~)

Code:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,f=1;
    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();
    return x*f;
}
int n,q;
bool flg[2000010];//表示标记(原题中的)为不为空。 
int fgl[2000010],fgr[2000010],a[2000010];
long long abj[2000010];//每一个梦境增加标记状态,状压,由于随机性,可以得到大概率不会超过64个未清除的标记,所以可以这样操作。(关键) 
struct tree{
	int l,r;
}t[2000010];
void pu(int id){
	flg[id]=abj[id]|flg[id<<1]|flg[id<<1|1];
} 
void get_abj(int id,int k){
	abj[id]|=k,flg[id]=1;
}
void get_new(int id,int k){
	abj[id]<<=k,fgl[id]+=k;
}
void get_a(int id,int k){
	a[id]+=k;
}
void get_d(int id,int k){
	if(k<64) abj[id]>>=k;
	else abj[id]=0;
	if(k<fgl[id]) fgl[id]-=k;
	else fgr[id]+=k-fgl[id],fgl[id]=0;	
}
void pd(int id){
	if(a[id]) a[id<<1]+=a[id],a[id<<1|1]+=a[id],a[id]=0;
	if(fgr[id]) get_d(id<<1,fgr[id]),get_d(id<<1|1,fgr[id]),fgr[id]=0;
	if(fgl[id]) get_new(id<<1,fgl[id]),get_new(id<<1|1,fgl[id]),fgl[id]=0;
	if(abj[id]) get_abj(id<<1,abj[id]),get_abj(id<<1|1,abj[id]),abj[id]=0;
}
void build(int id,int l,int r){
	t[id].l=l,t[id].r=r;
	if(l==r){
		a[id]=500000;
		return;
	}
	int mid=(l+r)>>1;
	build(id<<1,l,mid),build(id<<1|1,mid+1,r);
}
int query(int id,int x){
	if(t[id].l==t[id].r){
		return a[id];
	}
	pd(id);
	int mid=(t[id].l+t[id].r)>>1;
	if(x<=mid) return query(id<<1,x);
	else return query(id<<1|1,x);
}
void update3(int id,int l,int r){
	if(l<=t[id].l&&t[id].r<=r){
		get_abj(id,1);
		return;
	}
	pd(id);
	int mid=(t[id].l+t[id].r)>>1;
	if(l<=mid) update3(id<<1,l,r);
	if(r>mid) update3(id<<1|1,l,r);
	pu(id);
}
void update1(int id,int l,int r){
	if(l<=t[id].l&&t[id].r<=r){
		get_a(id,1),get_new(id,1);
		return;
	}
	pd(id);
	int mid=(t[id].l+t[id].r)>>1;
	if(l<=mid) update1(id<<1,l,r);
	if(r>mid) update1(id<<1|1,l,r);
	pu(id);
}
void update2(int id,int l,int r){
	if(l<=t[id].l&&t[id].r<=r){
		get_a(id,-1),get_d(id,1);
		return;
	}
	pd(id);
	int mid=(t[id].l+t[id].r)>>1;
	if(l<=mid) update2(id<<1,l,r);
	if(r>mid) update2(id<<1|1,l,r);
	pu(id);
}
void update4(int id,int l,int r){
	if(l<=t[id].l&&t[id].r<=r){
		if(t[id].l==t[id].r||(flg[id<<1]==0&&flg[id<<1|1]==0)){
			a[id]-=(abj[id]==0?0:63-__builtin_clzll(abj[id])); 
		}else{
			pd(id),update4(id<<1,l,r),update4(id<<1|1,l,r);	
		}
		abj[id]=fgl[id]=fgr[id]=flg[id]=0;
		return;
	}
	pd(id);
	int mid=(t[id].l+t[id].r)>>1;
	if(l<=mid) update4(id<<1,l,r);
	if(r>mid) update4(id<<1|1,l,r);
	pu(id);
}
int main(){
	n=read(),q=read();
	build(1,1,n);
	while(q--){
		int op,l,r;
		op=read(),l=read(),r=read();
		if(op==1) update1(1,l,r);
		if(op==2) update2(1,l,r);
		if(op==3) update3(1,l,r);
		if(op==4) update4(1,l,r);
		if(op==5) printf("%d\n",query(1,l));
	}
	return 0;
}
posted @ 2023-09-06 20:00  ArizonaYYDS  阅读(15)  评论(0)    收藏  举报