加载中…

返回上一页

暑期集训 8.13

题面链接(备用)



A.开根

直接调用库函数,O(1)出结果.(没想到pow居然可以乘小数次方)

代码不放了.

B.迭代

要求的是x进行n-1次 \(x=\frac{x+\frac{1}{x}}{2}\) 操作后的值.

将通式化简,\(\frac{\frac{a}{b}+\frac{b}{a}}{2}=\frac{a^2+b^2}{2ab}\) .
令其等于 \(\frac{a_1}{b_1}\) ,代表进行1次操作后它的值.

那么显然:

\[a_1+b_1=(a+b)^2 \]

\[a_1-b_1=(a-b)^2 \]

则第二次操作后:

\[a_2+b_2=(a_1+b_1)^2=(a+b)^4 \]

\[a_2-b_2=(a_1-b_1)^2=(a-b)^4 \]

推广到第n-1次操作后:

\[a_n-b_n=(a_1-b_1)^{2^{n-1}} \]

那么 \(f(x)\) 就可以轻松求出来了.

\[f(x)=\frac{(x+1)^{2^{n-1}}+(x-1)^{2^{n-1}}}{(x+1)^{2^{n-1}}-(x-1)^{2^{n-1}}} \]

这里 \(2^{n-1}\) 会炸 \(\text{long long}\) ,需要使用欧拉定理求一下.

点击查看代码
#include<bits/stdc++.h>
#pragma GCC optomize(2)
#define ll long long
#define rg register
#define rll rg ll
#define mod 1000000007
using namespace std;
static inline ll read()
{
	rll f=0,x=0;rg char ch=getchar();
	while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f?-x:x;
}
static inline void write(rll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);putchar(x%10|48);
}
ll t,x,n,fz,fm;
static inline ll ksm(rll a,rll b,rll p)
{
	rll ans=1;a%=p;
	for(rll i=b;i;i>>=1)
	{
		if(i&1) ans=ans*a%p;
		a=a*a%p;
	}
	return ans;
}
int main()
{
	t=read();
	while(t--)
	{
		x=read();n=read();
		fz=(ksm(x+1,ksm(2,n-1,mod-1),mod)+ksm(x-1,ksm(2,n-1,mod-1),mod))%mod;
		fm=(ksm(x+1,ksm(2,n-1,mod-1),mod)-ksm(x-1,ksm(2,n-1,mod-1),mod)+mod)%mod;
		write(fz*ksm(fm,mod-2,mod)%mod);puts("");
	}
	return 0;
}

C.致富之路

题解很详细了,依照它模拟即可. $$\downarrow$$ 假如选定第 $i$ 家工厂与第 $j$ 家商店,那么获利为 $max(qj−pi,0)×max(ej−di,0)$ . 对于两家工厂 $i, j$ ,如果 $pi≤pj$ 且 $di≤dj$ ,那么显然没有选 $j$ 的必要。 将工厂按 $p$ 从小到大排序,对于 $p$ 相同的情况,保留 $d$ 最 小的工厂。 按 $p$ 从小到大考虑每个工厂,如果它的 $d$ 比之前所有工厂 都要小,那么保留。 如此一来,有 $p_id_i+1$ 恒成立。

对于商店也是类似的道理。 对于两家商店 \(i, j\)
,如果 \(qi≤qj\)\(ei≤ej\) ,那么显然没有选 \(i\) 的必要。 将商店按 \(q\) 从小到大排序,对于 \(q\) 相同的情况,保留 \(e\) 最 大的商店。 按 \(q\) 从小到大考虑每个商店,维护一个 \(e\) 单调递减的栈, 将不满足 \(e\) 递减性质的商店剔除。 如此一来,也有 \(q_ie_i+1\) 恒成立。

假设有两家工厂 \(j < k\),如果 \(k\)\(j\) 优,那么有:

\[(qi−pj)(ei−dj)<(qi−pk)(ei−dk) \]

其中 \(pk−pj>0,dj−dk>0\) ,而对于 \(i\) 之后的所有商店, \(e\) 在减小,而 \(q\) 在增加。 故随着 \(i\) 的增大,不等式左侧的值只会越来越小,这说明一 旦 \(k\)\(j\) 优,那么 \(k\) 将永远比 \(j\) 优。

因此可以利用这种决策单调性,设计分治算法来解决问题。 令 \(solve(l,r, dl, dr)\) 表示在 \([l,r]\) 之间选择商店,在 \([dl, dr]\) 之 间选择工厂。 取 \(mid=l+r2\) ,取遍 \([dl, dr]\) 之间所有工厂,选取对商店 \(mid\) 最优的工厂 \(dm\) . 那么对于 \([l, mid)\) 的商店,它们最优的工厂只能在 \([dl, dm]\) 之间选取。同理对于 \((mid,r]\) 的商店,它们最优的工厂只能 在 \([dm, dr]\) 之间选取。 故 \(solve(l, mid 1, dl, dm)\)\(solve(mid + 1,r, dm, dr)\) 即可。

然而这么做是有问题的。 如果对于商店 \(mid\) 来说,并不存在一家工厂使得它们之间 的获利为正。 那么此时 \(mid\) 并不存在最优决策,不管 \(dm\) 取什么都会对 其他商店造成影响。 故在一开始将这种商店直接剔除即可。

对于 \(l,r\) 部分,是深度为 \(O(log m)\) 的分治。 对于每层来说,所有 \(solve\) 过程的 \([dl, dr]\) 区间长度加起来为 \(O(n)\) . 故分治部分的时间复杂度为 \(O(n log m)\) . 总时间复杂度 \(O(mlogm+nlogn+nlogm)\) .

点击查看代码
#include<bits/stdc++.h>
#pragma GCC optomize(2)
#define ll long long
#define rg register
#define rll rg ll
#define maxn 500001
#define mod 1000000007
using namespace std;
static inline ll read()
{
	rll f=0,x=0;rg char ch=getchar();
	while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f?-x:x;
}
static inline void write(rll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);putchar(x%10|48);
}
struct node
{
	ll d,p;
	inline friend bool operator<(rg node a,rg node b)
	{
		if(a.p==b.p) return a.d<b.d;
		return a.p<b.p;
	}
}a[maxn],aa[maxn];
struct node1
{
	ll e,q;
	inline friend bool operator<(rg node1 a,rg node1 b)
	{
		if(a.q==b.q) return a.e>b.e;
		return a.q<b.q;
	}
}b[maxn],bb[maxn];
ll cnt1,cnt2,m,n,ans=LLONG_MIN;
deque<ll> s;
static inline void solve(rll l,rll r,rll dl,rll dr)
{
	if(l>r) return;
	rll mid=(l+r)>>1,mx=LLONG_MIN,dm=0;
	for(rll i=dl;i<=dr;i++) if((b[mid].q-a[i].p)*(b[mid].e-a[i].d)>mx) mx=(b[mid].q-a[i].p)*(b[mid].e-a[i].d),dm=i;
	if(mx<0) return;
	ans=max(ans,mx);
	solve(l,mid-1,dl,dm);solve(mid+1,r,dm,dr);
}
int main()
{
	cnt1=read();n=read();
	for(rll i=1;i<=cnt1;i++) aa[i].p=read(),aa[i].d=read();
	sort(aa+1,aa+cnt1+1);
	for(rll i=1;i<=cnt1;i++) if(aa[i].p!=aa[i-1].p) a[++m]=aa[i];
	for(rll i=1;i<=n;i++) b[i].q=read(),b[i].e=read();
	sort(b+1,b+n+1);
	for(rll i=1;i<=n;i++) if(b[i].q!=b[i-1].q) bb[++cnt2]=b[i];
	for(rll i=1;i<=cnt2;i++)
	{
		while((!s.empty())&&bb[i].e>=bb[s.back()].e) s.pop_back();
		s.push_back(i);
	}
	n=0;
	while(!s.empty()) b[++n]=bb[s.front()],s.pop_front();
	solve(1,n,1,m);
	write(ans);
	return 0;
}

然后你就有了90分的好成绩.

运行编号用户问题结果内存耗时语言代码长度提交时间
1073718hszx0119答案错误90
37140
777
C++/Edit2783 B2022-08-13 16:23:13admin

然后是一波玄学更改.

把sort的顺序改一下(商店的都改成倒序排列),solve时商店和工厂反过来,然后就......AC了???

运行编号用户问题结果内存耗时语言代码长度提交时间
1073964hszx0119正确
36884
2068
C++/Edit3642 B2022-08-13 17:39:27admin
点击查看代码
#include<bits/stdc++.h>
#pragma GCC optomize(2)
#define ll long long
#define rg register
#define rll rg ll
#define maxn 500001
#define mod 1000000007
using namespace std;
static inline ll read()
{
	rll f=0,x=0;rg char ch=getchar();
	while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f?-x:x;
}
static inline void write(rll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);putchar(x%10|48);
}
struct node
{
	ll d,p;
	inline friend bool operator<(rg node a,rg node b)
	{
		if(a.p==b.p) return a.d<b.d;
		return a.p<b.p;
	}
}a[maxn],aa[maxn];
struct node1
{
	ll e,q;
	inline friend bool operator<(rg node1 a,rg node1 b)
	{
		if(a.q==b.q) return a.e>b.e;
		return a.q>b.q;
		//关于倒序排列,dalao是这么证明的:=的时候不满足决策单调性,-1排除了等于的情况
	}
}b[maxn],bb[maxn];
ll cnt1,cnt2,m,n,ans=LLONG_MIN;
ll mx[maxn];
deque<ll> s;
static inline void solve(rll l,rll r,rll dl,rll dr)
{
	if(l>r) return;
	rll mid=(l+r)>>1,dm=0;
	for(rll i=dl;i<=dr;i++)
	{
		if(b[i].e<a[mid].d&&b[i].q<a[mid].p) continue;//只是更改了一下判断方式,和前面的操作相同
		if((b[i].q-a[mid].p)*(b[i].e-a[mid].d)>mx[mid]) mx[mid]=(b[i].q-a[mid].p)*(b[i].e-a[mid].d),dm=i;
	}
	ans=max(ans,mx[mid]);
	solve(l,mid-1,dl,dm);solve(mid+1,r,dm,dr);
}
int main()
{
	m=read();n=read();
	for(rll i=1;i<=m;i++) a[i].p=read(),a[i].d=read();
	sort(a+1,a+m+1);rll mn=LLONG_MAX,ls;
	for(rll i=1;i<=m;)//只是更改了一下更新方式,和前面的操作相同
	{
		if(a[i].d<mn) mx[cnt1++]=LLONG_MIN,mn=a[i].d,a[cnt1]=a[i];
		ls=a[i].p;
		while(a[i].p==ls&&i<=m) i++;
	}a[++m]=aa[s.front()],s.pop_front();
	for(rll i=1;i<=n;i++) b[i].q=read(),b[i].e=read();
	sort(b+1,b+n+1);rll mx=LLONG_MIN;
	for(rll i=1;i<=n;)//只是更改了一下更新方式,和前面的操作相同
	{
		if(b[i].e>mx) mx=b[i].e,b[++cnt2]=b[i];
		ls=b[i].q;
		while(b[i].q==ls&&i<=n) i++;
	}	while((!s.empty())&&bb[i].e>=bb[s.back()].e) s.pop_back();
	solve(1,m=cnt1,1,n=cnt2);
	write(ans);
	return 0;
}


未完待续......

posted @ 2022-08-13 19:20  1Liu  阅读(67)  评论(0)    收藏  举报