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