2016.10.29 清北学堂NOIP冲刺班Day1 AM 考试总结

时间:2023-03-08 23:42:35
2016.10.29  清北学堂NOIP冲刺班Day1 AM 考试总结

成绩:满分300,我得了200,

1:90//前两个题目都是模拟,没用到什么其他算法,第一题有可能少考虑了一点细节

2:100

3:10//感觉是个DP,但是毫无思路,只打了个普通背包,10分而已。

题目+数据:http://pan.baidu.com/s/1bpj3SR1

下面是我的代码:

这个题目中我为了得到部分分,而特别判断了几组数据。

T1:

 /*
以后一定要仔细读数据范围,一定要。
数据范围中:20%的数据,只有秒数可能不同,言外之意就是可能相同。
而我的程序因为没有考虑到,时间相同时直接输出0000,。O__O"… 一个小技巧:计算时间时,可以把所有的时间都换算成秒,直接总秒数1-秒数2,不仅不会溢出,而且也方便计算。
*/
#include<iostream>
using namespace std;
#include<cstdio>
typedef long long ll;
struct Tim{
int n,y,r,x,f,m;
}tim1,tim2;
long long ans=;
int mon[]={,,,,,,,,,,,,};
bool is_runnian(int x)
{
if(x%==) return true;
if(x%!=&&x%==) return true;
return false;
} void input()
{
scanf("%d-%d-%d %d:%d:%d",&tim1.n,&tim1.y,&tim1.r,&tim1.x,&tim1.f,&tim1.m);
scanf("%d-%d-%d %d:%d:%d",&tim2.n,&tim2.y,&tim2.r,&tim2.x,&tim2.f,&tim2.m);
}
int main()
{
// freopen("two.in","r",stdin);
// freopen("two.out","w",stdout);
input();
if(tim1.n==tim2.n&&tim1.y==tim2.y&&tim1.r==tim2.r)
{
ans=(ll)(tim2.x*+tim2.f*+tim2.m)-(tim1.x*+tim1.f*+tim1.m);
}
else if(tim1.n==tim2.n)
{
ll d1=,d2=;
for(int i=;i<tim1.y;++i)
d1+=mon[i];
if(is_runnian(tim1.n)&&tim1.y>) d1++;
for(int i=;i<tim2.y;++i)
d2+=mon[i];
if(is_runnian(tim2.n)&&tim2.y>) d2++;
d1+=tim1.r;
d2+=tim2.r;
ans=(ll)(d2**+tim2.x*+tim2.f*+tim2.m)-(ll)(d1**+tim1.x*+tim1.f*+tim1.m); }
else{
ll d1=,d2=;
for(int i=;i<tim1.n;++i)
if(is_runnian(i)) d1+=;
else d1+=;
for(int i=;i<tim2.n;++i)
if(is_runnian(i)) d2+=;
else d2+=;
for(int i=;i<tim1.y;++i)
d1+=mon[i];
if(is_runnian(tim1.n)&&tim1.y>) d1++;
for(int i=;i<tim2.y;++i)
d2+=mon[i];
if(is_runnian(tim2.n)&&tim2.y>) d2++;
d1+=tim1.r;
d2+=tim2.r;
ans=(ll)(d2**+tim2.x*+tim2.f*+tim2.m)-(ll)(d1**+tim1.x*+tim1.f*+tim1.m);
}
if(ans) cout<<ans<<"";
else printf("0\n");
fclose(stdin);
fclose(stdout);
return ;
}

T2:

 #include<iostream>
using namespace std;
#include<cstdio>
#define N 100010
#define M 50010
#include<algorithm>
#include<queue>
typedef long long ll;
struct node{
ll tim;
bool operator <(node P)
const{return tim>P.tim;}
};
priority_queue<node>Q;
ll ren[N];
int n,m;
ll read()
{
ll ret=;
char s=getchar();
while(s<''||s>'')
{
s=getchar();
}
while(s>=''&&s<='')
{
ret=ret*+s-'';
s=getchar();
}
return ret;
}
void input()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
ren[i]=read();
for(int i=;i<=m;++i)
{
node X;
X.tim=ren[i];
Q.push(X);
}
}
int main()
{
freopen("death.in","r",stdin);
freopen("death.out","w",stdout);
input();
for(int i=m+;i<=n;++i)
{
node Now=Q.top();
Q.pop();
Now.tim+=ren[i];
Q.push(Now);
}
printf("%I64d",Q.top());
fclose(stdin);
fclose(stdout);
return ;
}

T3:

解析:

看了看题解:感觉也是这个道理:也许它并不需要Dp,比如在1*(*)中,我们为了价值最大,肯定先放价值大的(因为体积相同嘛),所以我们就把
价值大的先放进去就可以了。
这个题目注意两点即可: .有很多体积相同但是价值不同的物品,可以直接用贪心排序,就可以了。 .不必关注具体的背包中的物品如何放置,只需要关注能放多少个就可以了。因为我们总有办法使放到几乎满了或者满了的情况。 所以思路:
可以直接用n*m/,n*m/,计算数目,但是我们要想一想这样有没有可能出现错误。
n*m/2情况,如果n*m的背包1*2这么放,那么最后只可能
余下一个空位置,那么结果是不错的,但是如果是n*m的情况,我们可以发现,如果满足
n%== && m%== && (n== || m==),如果只放1*,最后会余下一个2*2的正方形不能再放,但是如果直接用n*m/3的话,结果就会多1了。
 #include<iostream>
using namespace std;
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 10010
int t,n,m,n1,n2,wu1[N],wu2[N];
int sumwu1[N],sumwu2[N];
typedef long long ll;
bool cmp1(int a,int b)
{
return a>b;
}
int main()
{
// freopen("eyesight.in","r",stdin);
// freopen("eyesight.out","w",stdout);
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d%d",&n,&m,&n1,&n2);
memset(sumwu1,,sizeof(sumwu1));
memset(sumwu2,,sizeof(sumwu2));
for(int i=;i<=n1;++i)
scanf("%d",&wu1[i]);
for(int i=;i<=n2;++i)
scanf("%d",&wu2[i]);
sort(wu1+,wu1+n1+,cmp1);
sort(wu2+,wu2+n2+,cmp1);
for(int i=;i<=n1;++i)
sumwu1[i]=sumwu1[i-]+wu1[i];
for(int i=;i<=n2;++i)
sumwu2[i]=sumwu2[i-]+wu2[i];
ll ans=;
int dalta;
if(n%==&&m%==&&(n==||m==)) dalta=;
else dalta=n*m%;
int sum=min(n2,(n*m-dalta)/);
for(int i=;i<=sum;++i)
ans=max(ans,(ll)(sumwu2[i]+sumwu1[min(n1,(n*m-*i)>>)]));
cout<<ans<<endl; }
fclose(stdin);
fclose(stdout);
return ;
}