NOIP 2017 模拟
2017 10 11
T1 :
题目 :
大意:用最少的长度为1和根号2的边围出一个多边形使面积大于等于给定值。
——正解思路:
手动计算找规律。
显然要用最少的边围出最大的面积。
当边为偶数时,我们需要找一个最接近正方形的矩形,此时边都在对角线上。
当边为奇数时,我们在偶数边的基础上,将最长边拆开,增加一条边使面积增大。
根据边数预处理加二分。
——我的乱搞:
疑似发现了什么数学规律,然后英勇牺牲。
tips:
好好学习数学。。。。
正解 :
#include<cstdio>
int main()
{
int n,t,l,r;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
l=r=1;
while(2*l*r<n) l==r ? ++r : l++;
printf("%d\n",2*l*r-n<1e-5 ? l+r<<1 : 2*l*r-l-0.5-n>0 ? (l+r)*2-1 : l+r<<1);
}
return 0;
}
T2 :
题目:
——正解思路:
这实际上是一个前缀最小值,所以拿数组维护一下就好了。
——我的乱搞:
诶WC,这竟然还是数学题??!
tips:
深感数学的重要性。
dp学得好的人数学都不会太差。 ——zgs
正解:
#include<cstdio>
#include<algorithm>
int n,__max,a[1000001];
inline int read()
{
int i=0;
char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') i=(i<<3)+(i<<1)+c-48,c=getchar();
return i;
}
int main()
{
n=read();
for(int i=1;i<=n;++i) a[i]=read();
std::sort(a+1,a+1+n);
__max=a[1];
for(int i=1;i<n;++i) if(a[i+1]>__max<<1) __max=a[i+1]-__max;
printf("%d\n",__max);
return 0;
}
T3 :
题目:
——正解思路:
首先求出关于ai单调不增的栈s, 然后从右向左扫,由于求的是最大的r - 1,所以现在r (当前在 i )是逐渐减小。
那么 l (假设为 j ) 也要逐渐减小才对答案有贡献,所以就存在一个 k ( k > j ) 满足 si - sk >= 0 ,对答案也是没贡献的。
所以我们找到在栈里一个最小的 j 满足 si - sj >= 0 即可。
——我的乱搞
以为又是什么数学题,搞了一套很奇奇怪怪的方法,然后。。。。。。
tips :
把上面两条tips中和一下。。
正解:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n,m,k,ans,index,a[1000001],s[1000001];
long long b[1000001];
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin>>n>>m;
for(int i=1;i<=n;++i) cin>>a[i];
while(m--)
{
cin>>k;
index=1;
s[index]=0;
for(int i=1;i<=n;++i)
{
b[i]=a[i]-k+b[i-1];
if(b[s[index]]>b[i]) s[++index]=i;
}
ans=0;
for(int i=n;i;--i)
{
while(b[s[index]]<=b[i]&&index>=0) --index;
ans=max(ans,i-s[index+1]);
}
cout<<ans<<" ";
}
return 0;
}