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;
}