【NOIP2014提高组】【Day1】【解题报告】

来源:互联网 发布:java web项目 license 编辑:程序博客网 时间:2024/06/03 18:16

T1:生活大爆炸版石头剪刀布

题目链接:http://codevs.cn/problem/3716/

题解:预处理出两两之间的关系。直接模拟即可。

代码:

#include<iostream>#include<cstdio>using namespace std;int ans1,ans2,t1,t2,c[30][30],n,l1,l2,a[501],b[501];int main(){  c[0][2]=1;c[0][3]=1;  c[1][3]=1;c[2][4]=1;  c[3][4]=1;c[1][0]=1;  c[4][0]=1;c[2][1]=1;  c[4][1]=1;c[3][2]=1;  c[0][0]=-1;c[1][1]=-1;  c[2][2]=-1;c[3][3]=-1;  c[4][4]=-1;  cin>>n>>l1>>l2;  for (int i=1;i<=l1;i++) cin>>a[i];  for (int i=1;i<=l2;i++) cin>>b[i];  t1=1;t2=1;  for (int i=1;i<=n;i++){     if(c[a[t1]][b[t2]]>0)ans1++;     else if (c[a[t1]][b[t2]]!=-1) ans2++; t1++;t2++;if (t1==l1+1) t1=1; if (t2==l2+1) t2=1;   }   cout<<ans1<<' '<<ans2<<endl;}
T2:联合权值

题目链接:http://codevs.cn/problem/3728/

题解:由数学公式可得2ab+2ac+2bc=(a+b+c)^2-a^2-b^2-c^2;

            然后枚举每个点,和这个相连的点两两之间一定能产生联合权值。

            代入那个公式直接算一下就好了。复杂度显然为O(n);

代码:

#include<iostream>#include<cstdio>#define N 200010#define P 10007using namespace std;struct use{int st,en;}e[N*2];long long ans,w[N],maxx;int cnt,n,a,b,point[N],next[N*2];void add(int x,int y){  next[++cnt]=point[x];point[x]=cnt;  e[cnt].st=x;e[cnt].en=y;}int main(){   scanf("%d",&n);   for (int i=1;i<=n-1;i++){scanf("%d%d",&a,&b);add(a,b);add(b,a);}   for (int i=1;i<=n;i++) scanf("%lld",&w[i]);   for (int i=1;i<=n;i++){     long long tp1(0),tp2(0),mx1(-1),mx2(-1);     for (int j=point[i];j;j=next[j]){       (tp1+=w[e[j].en])%=P;(tp2+=w[e[j].en]*w[e[j].en])%=P;       if (mx1<w[e[j].en]){mx2=mx1;mx1=w[e[j].en];}       else mx2=max(mx2,w[e[j].en]); }     (ans+=(tp1*tp1)%P-tp2+P)%=P;maxx=max(maxx,mx1*mx2);   }   cout<<maxx<<' '<<ans<<endl;}
T3飞扬的小鸟

题目链接:http://codevs.cn/problem/3729/

题解:设f[i][j]为从第0列走到(i,j)的最小步数.

             显然 f[i][j]=max(f[i-1][j+y[i-1]],f[i-1][j-k*x[i-1]]+k);

          这样直接转移显然是O(n*m*k)的。可以得到70分。

          观察一下后半部分.可以发现是完全背包。

          然后用完全背包优化一下就成了O(n*m).足以通过全部的数据。

代码:

#include<iostream>#include<cstdio>#include<cstring>#define N 10010#define inf 707406378using namespace std;int x[N],y[N],up[N],down[N],f[N][1010],n,m,k,p,ans;int main(){  scanf("%d%d%d",&n,&m,&k);up[n]=m+1;down[n]=0;  for (int i=0;i<n;i++) {scanf("%d%d",&x[i],&y[i]);up[i]=m+1;down[i]=0;}  for (int i=1;i<=k;i++){scanf("%d",&p);scanf("%d%d",&down[p],&up[p]);}  memset(f,127/3,sizeof(f));  for (int i=1;i<=m;i++) f[0][i]=0;  for (int i=1;i<=n;i++){     for (int j=x[i-1];j<=m;j++){      f[i][j]=min(f[i][j],f[i-1][j-x[i-1]]+1);      f[i][j]=min(f[i][j],f[i][j-x[i-1]]+1);       }      for (int j=m-x[i-1];j<=m;j++){       f[i][m]=min(f[i][m],f[i-1][j]+1);       f[i][m]=min(f[i][m],f[i][j]+1);     }        for (int j=down[i]+1;j<=up[i]-1;j++){       if (j+y[i-1]<=m) f[i][j]=min(f[i][j],f[i-1][j+y[i-1]]);     } for (int j=1;j<=down[i];j++) f[i][j]=inf; for (int j=up[i];j<=m;j++) f[i][j]=inf;      }ans=inf;int t=k;   for (int i=n;i>=1;i--){     for (int j=down[i]+1;j<up[i];j++) ans=min(ans,f[i][j]);     if (ans!=inf) break;if (up[i]!=m+1) t--;   }   if (t==k){cout<<1<<endl<<ans<<endl;}   else{cout<<0<<endl<<t<<endl;}}



3 0
原创粉丝点击