这个题开始未被收录,是因为太古怪了。其实,这个题考察了选手对rand()随机函数的应用。
用数学的正统方法,很难得到正确结果,效率也不高。命题人采用的办法是随机生成若干组(10000以上,同时避免超时)随机数,每组N个,针对不同的M进行试验,即可选出最大值。
在本机上调试时,会发现随着N的增大,最佳的M变化不是很大,N<=10000时,M<=10,这可能出乎多数人的意料。并且最佳的M随N的增大而增大,是增函数。于是正式提交程序时,这需对较小的M进行试验,提高时间效率,不会超时。
这个题型由于涉及随机化方法,在NOIP中尚未出现过,仅当作对未来题型的预测。
简单的说,就是枚举出所有可能的情况,例如限定随机数的范围是1-100,数列的长度是n,则共可能有100^n种可能的状态(完全随机,数允许重复)。首先给定参数m,在这100^n种数列中,分别按照规定的方法模拟,计算取到的数;再对这100^n个取到的数取平均值,就是要求的“加权平均值”。对每个可能的m都计算一次,再取使得“加权平均值”最大的m。
你能告诉我下面两个程序有什么差别导致答案不对吗?
#include<iostream>
using namespace std;
int main()
{
int n,m,i,j,k,ans=0,max,tot,t,num=1000;
cin>>n;
if(n==1) {cout<<0<<endl;return 0;}
if(n==1000)
num=1500;
for(i=1;i<=11;i++)
{
tot=0;
for(j=1;j<=num;j++)
{
max=0;
for(k=1;k<=i;k++) //差别,细节
{
t=rand()%100;
if(t>max) max=t;
}
for(k=i+1;k<=n;k++)
{
t=rand()%100;
if(t>max) break;
}
tot+=t;
}
if(tot>ans)
{
ans=tot;
m=i;
}
}
cout<<m<<endl;
system("pause");
return 0;
}
#include<iostream>
using namespace std;
int main()
{
int n,m,i,j,k,ans=0,max,tot,t,num=1000;
cin>>n;
if(n==1) {cout<<0<<endl;return 0;}
if(n==1000)
num=1500;
for(i=1;i<=11;i++)
{
tot=0;
for(j=1;j<=num;j++)
{
max=0;
for(k=1;k<i;k++) //差别,细节
{
t=rand()%100;
if(t>max) max=t;
}
for(k=i;k<=n;k++)
{
t=rand()%100;
if(t>max) break;
}
tot+=t;
}
if(tot>ans)
{
ans=tot;
m=i;
}
}
cout<<m-1<<endl;
system("pause");
return 0;
}