暑期集训 8.13
题面链接(备用)
A.开根
直接调用库函数,O(1)出结果.(没想到pow居然可以乘小数次方)
代码不放了.
B.迭代
要求的是x进行n-1次 操作后的值.
将通式化简, .
令其等于 ,代表进行1次操作后它的值.
那么显然:
则第二次操作后:
推广到第n-1次操作后:
那么 就可以轻松求出来了.
这里 会炸 ,需要使用欧拉定理求一下.
点击查看代码
#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.致富之路
对于商店也是类似的道理。 对于两家商店
,如果 且 ,那么显然没有选 的必要。 将商店按 从小到大排序,对于 相同的情况,保留 最 大的商店。 按 从小到大考虑每个商店,维护一个 单调递减的栈, 将不满足 递减性质的商店剔除。 如此一来,也有 恒成立。
假设有两家工厂 ,如果 比 优,那么有:
其中 ,而对于 之后的所有商店, 在减小,而 在增加。 故随着 的增大,不等式左侧的值只会越来越小,这说明一 旦 比 优,那么 将永远比 优。
因此可以利用这种决策单调性,设计分治算法来解决问题。 令 表示在 之间选择商店,在 之 间选择工厂。 取 ,取遍 之间所有工厂,选取对商店 最优的工厂 . 那么对于 的商店,它们最优的工厂只能在 之间选取。同理对于 的商店,它们最优的工厂只能 在 之间选取。 故 与 即可。
然而这么做是有问题的。 如果对于商店 来说,并不存在一家工厂使得它们之间 的获利为正。 那么此时 并不存在最优决策,不管 取什么都会对 其他商店造成影响。 故在一开始将这种商店直接剔除即可。
对于 部分,是深度为 的分治。 对于每层来说,所有 过程的 区间长度加起来为 . 故分治部分的时间复杂度为 . 总时间复杂度 .
点击查看代码
#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分的好成绩.
然后是一波玄学更改.
把sort的顺序改一下(商店的都改成倒序排列),solve时商店和工厂反过来,然后就......AC了???
点击查看代码
#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;
}
未完待续......
--END--
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/p/16583858.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!