码迷,mamicode.com
首页 > 其他好文 > 详细

0904解题报告

时间:2016-09-04 17:10:35      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:

 第一题

简单模拟,把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

第三题

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

0904解题报告

标签:

原文地址:http://www.cnblogs.com/chty/p/5839548.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!