[Contest] BC Round #79

可以打div1了,感谢带我飞的神犇ZZY

不熟悉莫比乌斯,T4没打出来,一直在给暴力调常数


A


懒得推了,乱搞,暴力枚举好了


#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

int main()
{
	int Q,n,m;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(Q);
	while (Q--)
	{
		read(n); read(m);
		int flag=0;
		for (int x=0;x<=360 && !flag;x++)
			for (int y=0;y<=360 && !flag;y++)
				if ((180*n-360)*m*x+(180*m-360)*n*y==360*n*m)
					flag=1;
		if (flag)
			printf("Yes\n");
		else
			printf("No\n");
	}
	
	return 0;
}



B


考虑从高位到低位贪心,对于每一位,如果x,y只有唯一的取法,那么只能这么取;否则贪心地必须使答案的这一位等于1。如果x,y都是0,1都能取,则设这是从右向左数第len位,因为x,y能取的值一定都是连续的一段,因此x,y的后len位都能取0111...1(len-1个1)和1000...0(len-1个0)(否则做不到从右向左数第len位都能取0,1)。也就是说,后len位的贡献一定能达到可能的上界111...1(len个1)。此时不必继续考虑后面的位。

如果x,y在这一位并不是0,1都能取,那么由于要使得答案的这一位等于1,也只有唯一的取法。

至此,这一位考虑完毕,然后根据选取的方案,修正一下x和y的范围,然后对后一位做即可。


#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(ll &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

ll a,b,c,d;

int main()
{
	#define MC 63
	ll Q;
	int x1,x2,y1,y2;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(Q);
	while (Q--)
	{
		ll ans=0;
		read(a); read(b); read(c); read(d);
		for (int i=MC;i>=0;i--)
		{
			x1=(bool)(a&(1LL<<i)); x2=(bool)(b&(1LL<<i));
			y1=(bool)(c&(1LL<<i)); y2=(bool)(d&(1LL<<i));
			if (x1==x2 && y1==y2)
			{
				if (x1!=y1)
					ans+=1LL<<i;
			}
			else if (x1!=x2 && y1==y2)
			{
				ans+=1LL<<i;
				if (y1==1)
				{
					a=a;
					b=(1LL<<i)-1;
				}
				else if (y1==0)
				{
					a=(1LL<<i);
					b=b;
				}
			}
			else if (y1!=y2 && x1==x2)
			{
				ans+=1LL<<i;
				if (x1==1)
				{
					c=c;
					d=(1LL<<i)-1;
				}
				else if (x1==0)
				{
					c=(1LL<<i);
					d=d;
				}
			}
			else if (y1!=y2 && x1!=x2)
			{
				ans+=(1LL<<(i+1))-1;
				break;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}


C


枚举K 然后就是一个单调栈维护成为最小值向左向右能延生的最长距离

调和级数 复杂度 O(n ln n)


#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

int n,a[300005];
int height[300005],cnt;
ll sum[300005];
int l[300005],r[300005];
int Stack[300005],pnt;

int main()
{
	#define MC 63
	int Q;
	ll ans;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(Q);
	while (Q--)
	{
		read(n); ans=0; 
		for (int i=1;i<=n;i++)
			read(a[i]);
		for (int k=1;k<=n;k++)
		{
			cnt=0;
			for (int j=1;j*k<=n;j++)
				height[++cnt]=a[j*k];
			for (int i=1;i<=cnt;i++)
				sum[i]=sum[i-1]+height[i];
			height[0]=-1<<30; 
			height[cnt+1]=-1<<30;
			pnt=0;
			Stack[++pnt]=0;
			for (int i=1;i<=cnt;i++)
			{
				while (height[Stack[pnt]]>=height[i]) Stack[pnt--]=0;
				if (Stack[pnt]==0) l[i]=1; else l[i]=Stack[pnt]+1;
				Stack[++pnt]=i;
			}
			pnt=0;
			Stack[++pnt]=cnt+1;
			for (int i=cnt;i;i--)
			{
				while (height[Stack[pnt]]>height[i]) Stack[pnt--]=0;
				if (Stack[pnt]==n+1) r[i]=n; else r[i]=Stack[pnt]-1;
				Stack[++pnt]=i;
			}
			for (int i=1;i<=cnt;i++)
				ans=max(ans,(sum[r[i]]-sum[l[i]-1])*height[i]*(ll)sqrt(k));
		}
		printf("%I64d\n",ans);
	}
	return 0;
}



实际上我并不熟悉莫比乌斯一套理论,%%Hillan

上官方题解


不妨令n\leq mnm

对于这一题,我们可以将所求的有多少对正整数对的最大公约数不为完全平方数转化为有多少对最大公约数为完全平方数。

那么我们设函数F\left(x\right)F(x),当且仅当xx为完全平方数时函数值为1,否则函数值为0。那么

Ans=\sum_{i=1}^n\sum_{j=1}^mF\left(\gcd\left(i,j\right)\right)Ans=i=1nj=1mF(gcd(i,j)) 设d=\gcd\left(i,j\right)d=gcd(i,j),那么

Ans=\sum_{i=1}^n\sum_{j=1}^mF\left(d\right)Ans=i=1nj=1mF(d)。 然后我们推一下这个式子:

Ans=\sum_{d=1}^nF\left(d\right)\times\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\left[\gcd\left(i,j\right)=1\right]Ans=d=1nF(d)×i=1dnj=1dm[gcd(i,j)=1]

=\sum_{d=1}^nF\left(d\right)\times\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\sum_{t|i,t|j}\mu\left(t\right) =\sum_{d=1}^nF\left(d\right)\times\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\mu\left(t\right)\times\lfloor\frac{n}{dt}\rfloor\times\lfloor\frac{m}{dt}\rfloor=d=1nF(d)×i=1dnj=1dmti,tjμ(t)=d=1nF(d)×i=1dnμ(t)×dtn×dtm 然后我们设G=dtG=dt,则Ans=\sum_{G=1}^n\left(t\right)\times\lfloor\frac{n}{G}\rfloor\times\lfloor\frac{m}{G}\rfloor\times\sum_{t|G}\mu\left(t\right)\times F\left(\frac{G}{t}\right)Ans=G=1nGn×Gm×tGμ(t)×F(tG) 然后我们设g(x)=\sum_{t|x}\mu\left(t\right)\times F\left(\frac{x}{t}\right)g(x)=txμ(t)×F(tx),则Ans=\sum_{G=1}^n\left(t\right)\times\lfloor\frac{n}{G}\rfloor\times\lfloor\frac{m}{G}\rfloor\times g(G)Ans=G=1nGn×Gm×g(G)

那么这道题的解法就出来了,如果我们已经确定gg函数的前缀和,那么就只需要类似莫比乌斯反演的方法O\left(\sqrt{n}\right)O(n)算一下即可。

g么,暴力算一下好了


#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x){
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int M=10000000;
int n,m;
ll sum[M+5];
int prime[5000005],num;
int mobius[M+5],vst[M+5];

inline void Pre()
{
	const int maxn=M;
	mobius[1]=1;
	for (int i=2;i<=maxn;i++)
	{
		if (!vst[i])
			mobius[i]=-1,prime[++num]=i;
		for (int j=1;j<=num && prime[j]*i<=maxn;j++)
		{
			vst[i*prime[j]]=1;
			if (i%prime[j]==0)
			{
				mobius[prime[j]*i]=0; break;
			}
			else
				mobius[prime[j]*i]=-mobius[i];
		}
	}
	int maxi=sqrt(maxn);
    for (int i=1;i<=maxi;i++)
	{
        int step=i*i;
        for(int tmp=step,j=1;tmp<=maxn;tmp+=step,j++)
			if(mobius[j])
				sum[tmp]+=mobius[j];
    }
    for (int i=1;i<=maxn;i++)
		sum[i]+=sum[i-1];
}

inline ll Solve(int n,int m)
{
	if (n>m) swap(n,m);
	ll ret=0;
	for (int i=1,j;i<=n;i=j+1)
	{
		j=min(n/(n/i),m/(m/i));
		ret+=(ll)(n/i)*(m/i)*(sum[j]-sum[i-1]);
	}
	return ret;
}


int main()
{
	int Q;
	ll ans;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	Pre();
	read(Q);
	while (Q--)
	{
		read(n); read(m);
		ans=(ll)n*m;
		ans-=Solve(n,m);
		printf("%lld\n",ans);
	}
	return 0;
}


E


二分加点分治 莫名其妙调了一下午...

sort啊,重心啊,可以预处理,这样每次check就是O(nlogn)


#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cstring>
#define V G[p].v
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

struct edge{
	int u,v,w;
	int next;
};

edge G[100005];
int head[50005],inum;

inline void add(int u,int v,int w,int p){
	G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p;
}

int n,m,K;

int sum,minimum,rt;
int size[50005],del[50005];

int ans,Mid;

int A[2000005],pnt;
int ls[2000005],rs[2000005],clk;
int Rt[50005],tik;

inline void Root(int u,int fa){
	size[u]=1;
	int maximum=0;
	for (int p=head[u];p;p=G[p].next)
		if (V!=fa && !del[V])
			Root(V,u),size[u]+=size[V],maximum=max(maximum,size[V]);
	maximum=max(maximum,sum-size[u]);
	if (minimum>maximum) minimum=maximum,rt=u;
}

namespace Pre{
	int a[50005],cnt;
	inline void Calc(int *a,int s,int t)
	{
		++clk;
		ls[clk]=pnt+1;
		for (int i=s;i<=t;i++) A[++pnt]=a[i];
		rs[clk]=pnt;
		sort(A+ls[clk],A+rs[clk]+1);
	}
	inline void dfs(int u,int fa,int dis)
	{
	    a[++cnt]=dis;
	    for (int p=head[u];p;p=G[p].next)
	        if (V!=fa && !del[V])
	            dfs(V,u,dis+G[p].w);
	}
	inline void Solve(int u)
	{
	    del[u]=1; cnt=0;
	    int last=cnt;
	    for (int p=head[u];p;p=G[p].next)   
	        if (!del[V])
	        {
	            dfs(V,u,G[p].w);
	            Calc(a,last+1,cnt);
	            last=cnt;
	        }
	    a[++cnt]=0;
	    Calc(a,1,cnt);
	    for (int p=head[u];p;p=G[p].next)
	        if (!del[V])
	        {
	            sum=size[V]; minimum=1<<30; Root(V,0); Rt[++tik]=rt;
	            Solve(rt);
	        }
	}
	inline void Work(){
		cl(del); clk=tik=0;
		sum=n; minimum=1<<30; Root(1,0); Rt[++tik]=rt;
		Solve(rt);
	}
}

inline int Calc()
{
	++clk;
	int s=ls[clk],t=rs[clk];
    int ret=0;
    int l=s,r=t+1;
    while (r-1>l && A[r-1]+A[l]>=Mid) r--;
    ret+=t-r+1;
    for (l++;l<=t;l++)
    {
    	r=max(r,l+1);
        while (r-1>l && A[r-1]+A[l]>=Mid) r--;
        ret+=t-r+1;
    }
    return ret;
}

inline void Solve(int u)
{
    del[u]=1;
    for (int p=head[u];p;p=G[p].next)   
        if (!del[V])
            ans-=Calc();
    ans+=Calc();
    for (int p=head[u];p;p=G[p].next)
        if (!del[V])
            Solve(Rt[++tik]);
}

int D[50005],icnt,iter;

inline void DEl(int u,int fa,int d){
	int last=iter;
	D[++icnt]=d;
	while (iter+1<=icnt && D[icnt]-D[iter]>=Mid) iter++;
	ans-=iter-1;
	for (int p=head[u];p;p=G[p].next)
		if (V!=fa)
			DEl(V,u,d+G[p].w);
	D[icnt--]=0;
	iter=last;
}

inline bool check(int mid){
	Mid=mid; ans=0; 
	cl(del); clk=tik=0;
	Solve(Rt[++tik]);
	icnt=0; iter=1; DEl(m,0,0);
	return ans>=K;
}

int maxd;

inline void dfs(int u,int fa,int d){
	maxd=max(maxd,d);
	for (int p=head[u];p;p=G[p].next)
		if (V!=fa)
			dfs(V,u,d+G[p].w);
}

int main()
{
	int Q,iu,iv,iw;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(Q);
	while (Q--)
	{
		read(n); read(m); read(K);
		for (int i=1;i<n;i++) read(iu),read(iv),read(iw),add(iu,iv,iw,++inum),add(iv,iu,iw,++inum);
		Pre::Work();
		maxd=0;
		dfs(m,0,0);
		int L=1,R=(maxd<<1)+1,MID;
		if (!check(0))
		{
			printf("NO\n");
			goto W;
		}
		while (L+1<R)
			if (check(MID=(L+R)>>1))
				L=MID;
			else
				R=MID;
		printf("%d\n",L);
W:		inum=0; cl(G); cl(head); pnt=0; 
	}
	return 0;
}




1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通;、 3本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看ReAdmE.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值