A.Hailstone HOTPO
这题意思是对n进行操作,当n为偶数时,n除以2,当n奇数时,n*3+1,直到n=1时结束。。。求这期间出现的最大值,很简单的题目。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int main()
{
int t,n,c,r;
RD(t);
while(t--)
{
RD(c);
RD(r);
n=r;
while(n!=1)
{
if(n%2==1)
{
n*=3;
n++;
}
else
{
n/=2;
}
r=max(r,n);
}
printf("%d %d\n",c,r);
}
return 0;
}
B.B-Casting
题意大体就是让你将一个B进制的数去模(B-1)得到的答案。简单的数制转化题,而且数的范围也不大,可以直接暴力,但oj就是不判题,所以就不贴代码了。
C.Pen Counts
这题就是将三只鸡放在三角形中,给你一个总距离,问你有多少种情况,其实就是给你三角形的周长,让你求三角形的数量。我们可以假设三角形边长为x,y,z,已知z,则有x+y=n-z,x-y<z,令x-y=t,(0<=t<z),求解得 x=(n-z+t)/2,y=(n-z-t)/2,对于y,ymax=(n-z)/2,ymin=(n-z-(z-1))/2。如果三边长不同,则+1。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int main()
{
int T,t,k,p,i,high,low,r;
RD(T);
while(T--)
{
RD(k);
RD(p);
r=0;
for(i=1; i<p; ++i)
{
low=max(i,(p-2*i)/2+1);
high=(p-i)/2;
if(low<=high)
{
t=0;
if(3*i<=p&&4*i>p)
{
t++;
}
if(3*i<p&&(p-i)%2==0)
{
t++;
}
r+=(high-low+1)*2-t;
}
}
printf("%d %d\n",k,r);
}
return 0;
}
D.Maximum Random Walk
这题题意还是挺难理解的,它要求的是走n步后,所有情况中最右边点的数学期望。
我定义了一个三维数组dp[2][2001][2001],2是滚动数组,保存的是走了i步,中间的2001是走到了j位置,最后的2001保存的是走到最右边的位置。分为刚好到达最右位置和不在最右位置两种情况。然后直接概率dp过程就行了。这是最暴力的过程了,最后一个样例干脆很慢才跑出来。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stdio.h>
#define N 1050
#define INF 99999999
using namespace std;
double dp[2][2003][2003];
int main()
{
int i,j,l,k,n,t;
double p,q,r,sum;
RD(t);
while(t--)
{
RD(k);
RD(n);
scanf("%lf%lf",&p,&q);
r=1.0-p-q;
memset(dp,0,sizeof(dp));
dp[0][1001][1001]=1;
for(i=1; i<=n; ++i)
{
for(j=1001-i; j<=1001+i; ++j)
{
for(l=max(1001,j);l<=1001+i; ++l)
{
if(l==j)
{
dp[i%2][j][l]=dp[(i-1)%2][j][l]*r+dp[(i-1)%2][j-1][l]*q+dp[(i-1)%2][j-1][l-1]*q;
}
else
{
dp[i%2][j][l]=dp[(i-1)%2][j][l]*r+dp[(i-1)%2][j-1][l]*q+dp[(i-1)%2][j+1][l]*p;
}
}
}
}
sum=0;
for(i=1001-n; i<=1001+n; ++i)
{
for(j=1001; j<=1001+n; ++j)
{
sum+=dp[n%2][i][j]*(j-1001);
}
}
printf("%d %.4f\n",k,sum);
}
return 0;
}
一道模拟题,关键在于它给的式子,F(i,j)=i/j*F(i-1,j-1)。我选择用两个二维数组保存分子和分母,依次得到每个值,但由于有些是整数,有些是负数,所以需要GCD和判负数。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 1000000007
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
long long f[401][401],g[401][401];
long long gcd(long long a,long long b)
{
if(a%b==0)
{
return b;
}
return gcd(b,a%b);
}
void ff()
{
f[0][1]=1;
f[1][1]=1;
f[1][2]=1;
g[0][1]=1;
g[1][1]=2;
g[1][2]=2;
int i,j;
long long l,r,ll,rr,m;
for(i=2;i<=400;++i)
{
l=r=1;
for(j=i+1;j>=2;--j)
{
ll=f[i-1][j-1]*i;
rr=g[i-1][j-1]*j;
m=gcd(ll,rr);
f[i][j]=ll/m;
g[i][j]=rr/m;
m=gcd(r,g[i][j]);
l=g[i][j]*l/m-f[i][j]*r/m;
r=r*g[i][j]/m;
}
f[i][1]=l;
g[i][1]=r;
m=gcd(f[i][1],g[i][1]);
f[i][1]/=m;
g[i][1]/=m;
}
}
int main()
{
ff();
int t,k,x,y;
RD(t);
double w;
while(t--)
{
RD(k);
RD(x);
RD(y);
printf("%d ",k);
if(f[x][y]%g[x][y]==0)
{
printf("%lld\n",f[x][y]/g[x][y]);
}
else
{
w=double(f[x][y])/double(g[x][y]);
if(w<0.0&&f[x][y]>0)
{
printf("%lld/%lld\n",-f[x][y],-g[x][y]);
}
else
{
printf("%lld/%lld\n",f[x][y],g[x][y]);
}
}
}
return 0;
}
F.The King's Ups and Downs
一道组合数学和dp结合的题目,在每个人进入队伍时,他都有两种情况:
1.到队伍两边:到队伍两边比较简单,就直接乘2就行了;
2.到队伍中间:我们可以假设有j个人在他的左边,有i-j-1个人在他的右边。这样的话就是dp[j]*dp[i-j-1]。而i-1个人中取出j个就是组合公式C(i-1,j)。因为只求了一半,所以需要乘2。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
long long f[22];
long long p(int a)
{
int i;
long long s=1;
for(i=1; i<=a; ++i)
{
s=s*i;
}
return s;
}
long long Cn(int x,int y)
{
return p(x)/p(y)/p(x-y);
}
void g()
{
int i,j;
f[1]=1;
f[2]=2;
f[3]=4;
for(i=4; i<=20; ++i)
{
f[i]+=f[i-1];
for(j=1; j<i-1; ++j)
{
if(j==1||(i-j)==2)
{
f[i]+=(f[j]*f[i-j-1]/2)*Cn(i-1,j);
}
else
{
f[i]+=(f[j]*f[i-j-1]/4)*Cn(i-1,j);
}
}
}
}
int main()
{
int t,n,k;
g();
RD(t);
while(t--)
{
RD(k);
RD(n);
printf("%d %lld\n",k,f[n]);
}
return 0;
}
H.Windmill Animation
一道计算几何题,看懂题意就很好做了。题意如下:给m个点,给一条与x轴夹角为angle的直线,直线从给定的l点穿过,直线开始以给定的l点逆时针旋转,当直线每次最初碰到一个点时,旋转轴点换成这个点,继续旋转。输出直线依次碰到的s个点。
想法:以转轴点向上和向下分别得到两条射线pa、pb,直线左边的点与射线pa比较得到夹角,直线右边的点与射线pb比较得到夹角。夹角最小的点就是下一个转轴点,然后更新射线。依次往下旋转,输出s次答案。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
#define pi 3.1415926535
#define INF 1e10
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
struct xl
{
double x,y;
int id;
}p[22];
double dot(xl a,xl b)//点积
{
return a.x*b.x+a.y*b.y;
}
double det(xl a,xl b)//叉积
{
return a.x*b.y-a.y*b.x;
}
double dis(xl a)//射线长度
{
return sqrt(a.x*a.x+a.y*a.y);
}
int main()
{
int T,k,m,s,l,i,j,ll,f,flag;
double ag,dr,ds,da,MAX;
xl pa,pb,px;
RD(T);
while(T--)
{
RD(k);
RD(m);
RD(s);
RD(l);
scanf("%lf",&ag);
for(i=1;i<=m;++i)
{
RD(p[i].id);
scanf("%lf%lf",&p[i].x,&p[i].y);
}
ll=l;
ag=ag*pi/180.0;
pa.x=cos(ag);
pa.y=sin(ag);
pb.x=-pa.x;
pb.y=-pa.y;
printf("%d",k);
FOR(1,s,i)
{
MAX=-INF;
FOR(1,m,j)
{
if(j==l||j==ll)
{
continue;
}
px.x=p[j].x-p[l].x;
px.y=p[j].y-p[l].y;
dr=det(pa,px);//判断上下
if(dr>0)
{
da=dot(pa,px)/dis(px)/dis(pa);//求角度cos值
if(da>MAX)
{
MAX=da;
flag=j;
f=1;
}
}
else if(dr<0)
{
da=dot(pb,px)/dis(px)/dis(pb);
if(da>MAX)
{
MAX=da;
flag=j;
f=-1;
}
}
}
printf(" %d",flag);
ll=l;
l=flag;
if(f==1)
{
pb.x=p[ll].x-p[l].x;
pb.y=p[ll].y-p[l].y;
pa.x=-pb.x;
pa.y=-pb.y;
}
else
{
pa.x=p[ll].x-p[l].x;
pa.y=p[ll].y-p[l].y;
pb.x=-pa.x;
pb.y=-pa.y;
}
}
printf("\n");
}
return 0;
}
J.Mystery
这题的要求就是累加确定位置,输出相应的位置的字符就行。注意输入输出。。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int T,n,i,j,id,ca,len;
char s[5555];
int main()
{
RD(T);
while(T--)
{
cin>>ca;
cout<<ca<<" ";
gets(s);
gets(s);
len=strlen(s);
RD(n);
id=0;
for(i=0; i<n; i++)
{
cin>>j;
id+=j;
id=(id%len);
if(id<0)
{
id+=len;
}
cout<<s[id];
}
printf("\n");
}
return 0;
}