130827組隊賽Regionals 2012, North America - Greater NY

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


E.Faulhaber's Triangle

一道模擬題,關鍵在於它給的式子,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;
}


發佈了44 篇原創文章 · 獲贊 49 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章