Good Bye 2017

Good Bye 2017

题目链接:http://codeforces.com/contest/908
A. New Year and Counting Cards(CF 908A)

#include<bits/stdc++.h> 
using namespace std;
int ans=0;char s[100];
int main()
{
  scanf(" %s",s+1);
  int len=strlen(s+1);
  for(int i=1;i<=len;i++)
  {
    if(s[i]=='a')ans++;
    if(s[i]=='e')ans++;
    if(s[i]=='i')ans++;
    if(s[i]=='o')ans++;
    if(s[i]=='u')ans++;
    if(s[i]=='1')ans++;
    if(s[i]=='3')ans++;
    if(s[i]=='5')ans++;
    if(s[i]=='7')ans++;
    if(s[i]=='9')ans++;
  }
  printf("%d\n",ans);
  return 0;
}

B. New Year and Buggy Bot(CF 908B)
爆搜爆判

#include<bits/stdc++.h>
#define N 55
#define M 105
using namespace std;
int n,m,ans,len,p[5],flag[5],X1,Y1;
char s[M],w[N][N];
int t1[]={-1,0,0,1};
int t2[]={0,-1,1,0}; 

void dfs(int X)
{
  if(X==4)
  {
    int x=X1,y=Y1;
    for(int i=1;i<=len;i++)
    {
      int tp=p[s[i]-48];
      x=x+t1[tp];y=y+t2[tp];
      if(w[x][y]=='E'){ans++;return;}
      if(w[x][y]=='#')return;
    }
    return;
  } 
  for(int i=0;i<4;i++)
  if(!flag[i])
  {
    flag[i]=1;p[X]=i;
    dfs(X+1);flag[i]=0;
  }
}

int main()
{
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
      scanf(" %c",&w[i][j]);
      if(w[i][j]=='S')X1=i,Y1=j;
    }
  for(int i=0;i<=n+1;i++)w[i][0]='#',w[i][m+1]='#';
  for(int i=0;i<=m+1;i++)w[0][i]='#',w[n+1][i]='#';
  scanf(" %s",s+1);
  len=strlen(s+1);dfs(0);
  printf("%d\n",ans);
  return 0;
}

C. New Year and Curling(CF 908C)
每个圆,对每个前面的圆求相切对应的圆心,取最大。

#include<bits/stdc++.h>
#define N 1005
using namespace std;
int n,r,x[N];double y[N];
double pf(double x){return x*x;}
double cal(int i,int j)
{
  return sqrt(pf(2.0*r)-pf(x[i]-x[j]))+y[j];
}

int main()
{
  scanf("%d%d",&n,&r);
  for(int i=1;i<=n;i++)
  {
    scanf("%d",&x[i]);
    for(int j=1;j<i;j++)
    {
      if(abs(x[j]-x[i])>2*r)continue;
      y[i]=max(y[i],cal(i,j));
    }
  }
  for(int i=1;i<=n;i++)printf("%.10lf ",y[i]+r);
  printf("\n");
  return 0;
}

emmm两个半小时就过了这仨傻逼题,全场推D退不出来,果然需要点智商的题就不会做。

D. New Year and Arbitrary Arrangement(CF 908D)
题解:
f[i][j]表示i个‘a’j个‘ab’的概率。
对于每个状态考虑两种转移,一种加一个a转移到f[i+1][j],一种加一个b转移到f[i][i+j]。
本题难点在于状态数有无限个。
对于当前‘ab’数不够而再加上一个‘b’就够的状态,之后可以选无穷多个a,所以要用无穷级数推公式直接算。
在最开始放‘b’显然是没用的,所以初始状态是f[1][0],即先放一个‘a’,最后再用无穷级数推前面加b的概率。
其实这题不难啊怎么就没做出来。。。

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define N 1005
using namespace std;
int n;ll Pa,Pb,pa,pb,ans,f[N][N];//i个a,j个ab 
ll Pow(ll a,ll b)
{
  ll res=1;
  while(b)
  {
    if(b&1)res=res*a%mod;
    a=a*a%mod;b>>=1;
  }
  return res;
} 

int main()
{
  scanf("%d%I64d%I64d",&n,&Pa,&Pb);
  pa=Pa*Pow(Pa+Pb,mod-2)%mod;
  pb=Pb*Pow(Pa+Pb,mod-2)%mod;
  f[1][0]=1;
  for(int i=1;i<=n;i++)
    for(int j=0;j<=n;j++)
    {
      if(i+j<n)
      {
        f[i+1][j]=(f[i+1][j]+f[i][j]*pa)%mod;
        f[i][j+i]=(f[i][j+i]+f[i][j]*pb)%mod;
      }
      else
      {
        if(j==n)ans=(ans+f[i][j]*j)%mod;
        if(j<n)ans=(ans+f[i][j]*(i+j+pa*Pow(pb,mod-2)%mod)%mod)%mod;
        //每一种无穷级数不到n的都要算无穷级数 
      }
    }
  printf("%d\n",ans);
  return 0;

E. New Year and Entity Enumeration
首先不考虑T的限制。
定义S集合为我们所求的集合。
f[i]表示S集合中包含i这个位的最小的数字。
可以证明对于任意不同的f[i],他们之间的&=0.
也就是说,对于一个合法的S,f[0]..f[m]去重之后等价于2^m-1的一组划分。
所以将m位进行划分,每一组的f[i]相同,每一种划分对应一组合解。
不需要考虑同组不同划分的情况,因为有取反操作。
所以不考虑T,ans=bell[m],其中bell为贝尔数。
考虑T,按照n个数在不同位上的状态将m个位数分类,对于每一类答案相互独立。套用bell数算答案即可。
数学渣表示这题好难emmm。

#include<bits/stdc++.h>
#define mod 1000000007 
#define ll long long
#define N 55
#define M 1005
using namespace std;
int n,m,ans=1,bell[M],c[M][M];char s[N][M];
map<ll,int>w;

ll get(int x)
{
  ll res=0;
  for(int i=1;i<=n;i++)
    res=(res<<1)+s[i][x]-48;
  return res;
}

int main()
{
  scanf("%d%d",&m,&n);
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)scanf(" %c",&s[i][j]);
  for(int i=1;i<=m;i++)w[get(i)]++;

  c[0][0]=1;bell[0]=1;
  for(int i=1;i<=m;i++)
    for(int j=0;j<=i;j++)
    {
      c[i][j]=(c[i-1][j-1]+(ll)j*c[i-1][j])%mod;
      bell[i]=(bell[i]+c[i][j])%mod;
    }

  for(int i=1;i<=m;i++)
  {
    ll num=get(i);
    ans=(ll)ans*bell[w[num]]%mod;
    w[num]=0;
  }
  printf("%d\n",ans);
  return 0;
} 

F. New Year and Rainbow Roads(CF 908F)
题解:
这真的是一个傻逼题比DE都简单。不知道为什么会排在F,可能贪心不好证?
反正当时这题看都没看,不然也不会这么惨吧。
把所有点按绿点隔开,对于每两个绿点中间的红点和蓝点分别考虑。
考虑红点,要么连这两个绿点,并把这两个绿点和区间内红点按顺序依次连接,并去掉一条最长的。
蓝点和红点一样。
然后就过了。

#include<bits/stdc++.h>
#define ll long long
#define N 300005
using namespace std;
int n,c[N],tg,tr,tb,pr=1,pb=1,g[N],r[N],b[N];
ll ans;

int main()
{
  int x;char ch;
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
  {
    scanf("%d %c",&x,&ch);
    if(ch=='G')g[++tg]=x;
    if(ch=='R')r[++tr]=x;
    if(ch=='B')b[++tb]=x;
  }
  for(;r[pr]<g[1]&&pr<=tr;pr++)ans+=r[pr+1]-r[pr];
  if(pr>1)ans+=g[1]-r[pr];
  for(;b[pb]<g[1]&&pb<=tb;pb++)ans+=b[pb+1]-b[pb];
  if(pb>1)ans+=g[1]-b[pb];
  for(int i=2;i<=tg;i++)
  {
    ll res=0;int maxr=0,maxb=0;
    for(int pre=g[i-1];r[pr]<g[i]&&pr<=tr;pre=r[pr++])
      maxr=max(maxr,r[pr]-pre);
    if(r[pr-1]>g[i-1])maxr=max(maxr,g[i]-r[pr-1]);
    else maxr=g[i]-g[i-1];
    for(int pre=g[i-1];b[pb]<g[i]&&pb<=tb;pre=b[pb++])
      maxb=max(maxb,b[pb]-pre);
    if(b[pb-1]>g[i-1])maxb=max(maxb,g[i]-b[pb-1]);
    else maxb=g[i]-g[i-1];
    ans+=min((g[i]-g[i-1])*3-maxr-maxb,(g[i]-g[i-1])*2);
  }
  for(int pre=g[tg];pr<=tr;pre=r[pr++])ans+=r[pr]-pre;
  for(int pre=g[tg];pb<=tb;pre=b[pb++])ans+=b[pb]-pre;
  if(!tg)ans-=r[1]+b[1];
  printf("%I64d\n",ans);
  return 0;
} 

猜你喜欢

转载自blog.csdn.net/wcy_1122/article/details/78940244