codeforces 283,284(Round #174)题解

来源:互联网 发布:linux下好用的输入法 编辑:程序博客网 时间:2024/04/27 23:30

2A:暴力即可,有数学方法,答案即为phi(phi(p)),具体证明详见

http://jijiwaiwai163.blog.163.com/blog/static/186296211201261133849397/

2B:记录'I'的个数a,'A'的个数b,a=0显然答案就是b,a=1答案显然只能为1,a>=2答案显然为0。

2C(1A):由于1~i均加一个值,完全没必要1~i都记录,只需记录每次加的最后一个数加了多少即可,每次弹出的时候,把最后一个数累加的加到前面一个数即可,注意,弹出时一定要清零,否则以后再加的时候就错了(thx谷神T_T)

上代码:

#include<cstdio> #include<algorithm>#include<iostream>#include<cstring>#include<cmath>using namespace std;const int N=200005;int a[N],w[N];int main(){     int i,t,n;     scanf("%d",&n);     double sum=0;     int l=1;     int x,y;     for(i=0;i<n;++i)     {       scanf("%d",&t);       if(t==1)       {          scanf("%d%d",&x,&y);          a[x]=a[x]+y;          sum+=(double)x*y;       }       if(t==2)       {          scanf("%d",&x);          sum+=(double)x;          w[++l]=x;       }       if(t==3)       {          sum-=(double)(w[l]+a[l]);          a[l-1]+=a[l];          w[l]=a[l]=0;          l--;       }       printf("%.6lf\n",sum/(double)l);     }     return 0;}

2D(1B):首先看数据范围,显然不能暴力。然后又会想到每个数列主要区别在于a1加的值,其他区别在于第二步从第几个数计算。所以我们只需记忆化搜索出从a[2],到a[n]开始计算出的每个y的值,再分别加上i即可。

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;const int N=200005;int n;long long a[N],y[N][2];bool v[N][2];long long dfs(int x,int t){  if(x<=0 || x>n) return 0;  if(x==1) return -1;  if(v[x][t]) return y[x][t];  v[x][t]=true;  y[x][t]=-1;  if(t==1) y[x][t]=dfs(x-a[x],0);   if(t==0) y[x][t]=dfs(x+a[x],1);  if(y[x][t]!=-1) y[x][t]+=a[x];  return y[x][t];}int main(){    int i;    scanf("%d",&n);    for(i=2;i<=n;++i)     scanf("%I64d",&a[i]);    for(i=2;i<=n;++i)  if(!v[i][1]) dfs(i,1);//记忆化搜素,搜索a[2]到a[n]状态开始计算出的值     for(i=1;i<n;++i)     if(y[i+1][1]==-1) printf("-1\n");     else printf("%I64d\n",y[i+1][1]+i);       return 0;}
2E(1C):完全背包,比较水,关键在于有物品数量是严格大于其他物品的,这种情况只需把前者价值加上后者即可。
注意这种物品有两种,一种是只限制别人,不被限制,另一种是限制别人同时自己也被限制。搞个ind[]数组存储,
先存第一类,再存第二类,这样第一类价值可以累加到第二类上,第二类价值可以加到只被限制的物品上,完全背包即可

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>using namespace std;const int N=305,MOD=1000000007;int w[N],p[N],vis[N],dep[N],ind[N],f[100005];int main(){     int i,j,n,q,t;     int x,y;     scanf("%d%d%d",&n,&q,&t);     for(i=1;i<=n;++i) scanf("%d",&w[i]);     for(i=1;i<=q;++i)     {       scanf("%d%d",&x,&y);       p[x]=y;       vis[x]=1;       dep[y]++;     }     int tot=0;     for(i=1;i<=n;++i) if(vis[i] && !dep[i]) ind[++tot]=i;     for(i=1;i<=tot;i++)      {int now=ind[i];if(vis[p[now]] && dep[p[now]]==1) ind[++tot] = p[now]; }     if(tot!=q) printf("0");     else     {       for(i=1;i<=tot;++i)       {         int now=ind[i];         int af=p[now];         w[af]+=w[now];         t=t-w[now];         if(t<0) {printf("0");return 0;}       }          f[0]=1;          for(i=1;i<=n;++i)          {            for(j=w[i];j<=t;++j)            {               f[j]=(f[j]+f[j-w[i]])%MOD;            }          }          printf("%d",f[t]);     }     return 0;}

1D:不错的题,f[n]表示满足条件的数有多少,ans=min(n-f[n])。对于j<i如果a[i]为奇数且a[j]%a[i]=0,显然满足;
如果a[i]为偶数,a[j]%a[i]=a[i]/2,也满足(想一想,为什么)。如果a[i]为偶数a[i-2],a[i-1],a[i]若都想成立,
a[i-1]需为a[i]/2(我自己YY感觉的T_T,大致推了一下)。

#include<cstdio>//dp,记录满足条件最多多少个数即可 #include<iostream>#include<algorithm>using namespace std;const int N=5005;long long a[N],f[N];int main(){      int i,j,n;      scanf("%d",&n);      for(i=1;i<=n;++i)  scanf("%I64d",&a[i]);      for(i=1;i<=n;++i)      {         long long x=a[i];         f[i]=1;         for(j=i-1;j>=1;--j)         {           if((x&1 && a[j]%x==0)|| (!(x&1) && a[j]%x==x/2)) f[i]=max(f[i],f[j]+1);           if(!(x&1)) x=x>>1;         }      }      long long ans=1000000;      for(i=1;i<=n;++i)       ans=min(ans,n-f[i]);      printf("%I64d",ans);      return 0;}





原创粉丝点击