code+7正式赛划水记+HardA~C题解

被同年级的吊锤了

划水

sometimes naive

2:00看题,感觉不是很可做

20分的时候有人切了T2,看了一下发现是sb题,20min切掉

T1写了暴力找规律无果,交了10分上去

去看T3,发现白给40分直接写

150分以为稳了,还有1h的时候搞T1

想到从后往前构造(?),因为决策点并不多并且主要时间在二分上所以是正解(暴论)

打出了65,稍微调一下变成93

这时还剩30min,大概是30多名

然后看着排名飞速往后掉慌得一笔,去搞T3p质数的部分分搞不出来(并没有发现与模4有关)

最后10min开始卡T1,45名

最后5min掉出50名

最后3min想到缩二分上下界,52名

最后1min一Fa♂入魂,咸鱼翻身√

A

https://next.xuetangx.com/live/live20200523it002/live20200523it002/4071197/5468641

k<=10^12

题解是从前往后做的,设i以及i之后的操作次数为x,则最后一次一定是i,并且从后往前每i+1次中有一次i

那么i被操作的次数为ceil(x/(i+1)),a则要加上第一次i前面的那一段,即a[i]=i-(x-1)%(i+1)

然后把x剪掉ceil(x/(i+1)),往后做即可

二分n,然后奇妙卡上下界

也可以从后往前做,那就会遇到要决策0或i的地方,因为决策点不多所以可以过

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
#define file
using namespace std;

int i,j,k,l,r,mid,n,len,ss;
ll a[10000001],K,s,sum;
char st[20000001];

ll pd(int n,ll s,ll sum,bool tp)
{
	int i,j,k,l,ss;
	
	fd(i,n,1)
	{
		ss=s%i;
		if (!(ss)) {if (!tp) a[i]=0; else a[i]=i;}
		else
		a[i]=i-ss;
		s+=(a[i]+s)/i;sum+=a[i];
	}
	
	return sum;
}
void Write(int t)
{
	char a[10];
	int i=0;
	
	if (!t) {st[++len]='0';st[++len]=' ';return;}
	
	while (t) a[++i]=t%10,t/=10;
	while (i) st[++len]=a[i--]+'0';
	st[++len]=' ';
}

int main()
{
	#ifdef file
	freopen("a.in","r",stdin);
	#endif
	freopen("a.out","w",stdout);
	
	scanf("%lld",&K);
	l=1;r=2000000;
	if (K>100000000000ll)
	l=floor(sqrt(K)*1.77244),r=floor(sqrt(K)*1.77255);
	while (l<r)
	{
		mid=(l+r)/2;a[mid]=mid;
		if (pd(mid-1,1,0,1)<K)
		l=mid+1;
		else
		r=mid;
	}
	
	n=l;a[n]=n;s=1;sum=n;
	fd(i,n-1,1)
	{
		ss=s%i;
		if (!(ss))
		{
			if (pd(i-1,s+s/i,sum-n,1)>=K)
			a[i]=0;
			else
			a[i]=i;
		}
		else
		a[i]=i-ss;
		s+=(a[i]+s)/i;sum+=a[i];
	}
	
	len=-1;
	Write(n);st[++len]='
';
	fo(i,1,n) Write(a[i]);st[++len]='
';
	fwrite(st,1,len,stdout);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

B

直接求询问i的答案,把更新i所要的区间[ki+1,(k+1)i]挂在线段树上,如果操作1经过了区间就更新i的答案

简单题

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define low(x) ((x)&-(x))
#define ll long long
//#define file
using namespace std;

int b[100001],n,Q,i,j,k,l,tp,x,y,z;
vector<int> tr[400001];
ll Tr[100001],Tr2[100001];

void Change(int t)
{
	while (t<=n) {++Tr[t]; t+=low(t);}
}
ll Find(int t)
{
	ll ans=0; while (t) {ans+=Tr[t];t-=low(t);};return ans;
}
void Change2(int t)
{
	while (t<=n) {++Tr2[t]; t+=low(t);}
}
ll Find2(int t)
{
	ll ans=0; while (t) {ans+=Tr2[t];t-=low(t);};return ans;
}

void change(int t,int l,int r,int x,int y,int s)
{
	int mid=(l+r)/2;
	if (x>y) return;
	
	if (x<=l && r<=y) {tr[t].push_back(s);return;}
	
	if (x<=mid) change(t*2,l,mid,x,y,s);
	if (mid<y) change(t*2+1,mid+1,r,x,y,s);
}
void find(int t,int l,int r,int x)
{
	int mid=(l+r)/2,tot=tr[t].size(),i,s;
	
	if (tot)
	{
		fo(i,0,tot-1)
		{
			s=tr[t][i];
			if (((l-1)/s)<b[s]) continue;
			
			Change(s);++b[s];
			while (b[s]*s<=n && Find2(min((b[s]+1)*s,n))-Find2(b[s]*s)) ++b[s],Change(s);
			change(1,1,n,b[s]*s+1,min((b[s]+1)*s,n),s);
		}
		tr[t].clear();
	}
	if (l==r) return;
	
	if (x<=mid) find(t*2,l,mid,x);
	else
	find(t*2+1,mid+1,r,x);
}

int main()
{
	#ifdef file
	freopen("b.in","r",stdin);
	#endif
	
	scanf("%d%d",&n,&Q);
	fo(i,1,n) change(1,1,n,1,i,i);
	for (;Q;--Q)
	{
		scanf("%d",&tp);
		if (tp==1)
		{
			scanf("%d",&x);
			Change2(x);
			find(1,1,n,x);
		}
		else
		{
			scanf("%d%d",&x,&y);
			printf("%lld
",(Find(y)-Find(x-1))+(y-x+1));
		}
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

C

n<=10^5,p<=10^7

40分直接枚举一个丢到桶里,然后把枚举另一个计算

p是质数的时候答案长这样

因为p没有平方因子,所以把p分解成Πpi后直接crt

即求a^2+b^2=x%p等价于求a^2+b^2=x%pi方程组的解

然后可以求出每个的解乘起来

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

int p[3163],T,n,i,j,k,l,P,x,len;
bool f[3163];
ll ans;

void init()
{
	int i,j,k,l;
	
	fo(i,2,3162)
	{
		if (!f[i]) p[++len]=i;
		fo(j,1,len)
		if (i*p[j]<=3162)
		{
			f[i*p[j]]=1;
			if (!(i%p[j])) break;
		}
		else
		break;
	}
}

int js(int p)
{
	if (p%4==1) {if (!(x%p)) return p*2-1;return p-1;}
	if (p%4==3) {if (!(x%p)) return 1;return p+1;}
}

int main()
{
	#ifdef file
	freopen("c.in","r",stdin);
	freopen("c.out","w",stdout);
	#endif
	
	init();
	scanf("%d",&T);
	for (;T;--T)
	{
		scanf("%d%d",&P,&x);ans=1;
		
		fo(i,1,len)
		if (!(P%p[i]))
		P/=p[i],ans*=js(p[i]);
		if (P>1) ans*=js(P);
		
		printf("%lld
",ans);
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/gmh77/p/12951279.html