0904解题报告

 第一题

简单模拟,把s拆成二进制形式,然后统计有多少个一,将  ans/n*m   化简即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<ctime>
 7 #include<algorithm>
 8 using namespace std;
 9 long long n,m,s,ans;
10 inline long long read()
11 {
12     long long x=0,f=1;  char ch=getchar();
13     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
14     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
15     return x*f;
16 }
17 long long gcd(long long a,long long b)  {return b==0?a:gcd(b,a%b);}
18 int main()
19 {
20     freopen("huajitree.in","r",stdin);
21     freopen("huajitree.out","w",stdout);
22     n=read();  m=read();  s=read();
23     while(s)  {if(s%2==1)  ans++;  s/=2;}
24     long long r=gcd(ans,n*m);
25     if(!ans)  printf("0\n");
26     else printf("%I64d/%I64d\n",ans/r,m*n/r);
27     return 0;
28 }
View Code

 第二题

无力吐槽贪心水过,请看正解动态规划。

用sumv和sumh分别维护v和h的前缀和,f[i]表示将前i件物品放入背包的最小代价,那么很容易写出状态转移方程:f[i]=min{f[i],f[j]+sumh[i]*(sumv[i]-sumv[j])}

O(n^2)的时间复杂度,可以过掉60分,然后需要进行斜率优化。

假设从k转移到i比j更优,则有f[k]+sumh[i]*sumv[i]-sumh[i]*sumv[k]<f[j]+sumh[i]*sumv[i]-sumh[i]*sumv[j]

化简得(f[k]-f[j])/(sumv[k]-sumv[j])<sumh[i]

这就是斜率表达式了,然后维护凸包即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<ctime>
 7 #include<algorithm>
 8 #define MAXN 1000010
 9 using namespace std;
10 long long n,f[MAXN],v[MAXN],h[MAXN],sumv[MAXN],sumh[MAXN],q[MAXN];
11 inline long long read()
12 {
13     long long x=0,f=1;  char ch=getchar();
14     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
15     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
16     return x*f;
17 }
18 long long slop(long long a,long long b){return (f[a]-f[b])/(sumv[a]-sumv[b]);}
19 int main()
20 {
21     freopen("pack.in","r",stdin);
22     freopen("pack.out","w",stdout);
23     n=read();
24     for(int i=1;i<=n;i++)  
25     {
26         v[i]=read();  
27         h[i]=read();
28         sumv[i]=v[i]+sumv[i-1];
29         sumh[i]=h[i]+sumh[i-1];
30         f[i]=sumv[i]*sumh[i];
31     }
32     f[1]=v[1]*h[1];  
33     long long l=0,r=0;
34     for(int i=1;i<=n;i++)
35     {
36         while(l<r&&slop(q[l],q[l+1])<sumh[i])l++;
37         long long t=q[l];
38         f[i]=f[t]+sumh[i]*(sumv[i]-sumv[t]);
39         while(l<r&&slop(q[r-1],q[r])>slop(q[r],i))r--;
40         q[++r]=i;
41     }
42     printf("%I64d\n",f[n]);
43     return 0;
44 }
View Code

第三题

线段树维护图的连通性,考试时完全没有想到,写了一个暴力,然后挂了。

这题是bzoj1018原题。

题解:http://www.cnblogs.com/chty/p/5895867.html

posted @ 2016-09-04 15:57  chty  阅读(142)  评论(0编辑  收藏  举报