2013山东省赛回顾A、F、I

A题:

题目大意:按照逆时针顺序给出等边三角形的两个顶点,求另一个顶点。


向量旋转。。。之前做过SGU的一道关于向量旋转的题,在这里用上了。

根据已知两点坐标,将向量逆时针旋转π/3度,即可求得另一顶点坐标。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 160
#define Pi acos(-1.0)
typedef double db;
struct P
{
    db x,y;
}p[N];
P rol(P s,P e,db a,db k)   //向量se,逆时针旋转a度后,乘上比例系数k,返回新的终点坐标
{
    P c;
    db x=e.x-s.x,y=e.y-s.y;
    c.x=s.x+k*(x*cos(a)-y*sin(a));
    c.y=s.y+k*(x*sin(a)+y*cos(a));
    return c;
}
db dis(P a,P b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        P a,b,c;
        scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
        c=rol(a,b,Pi/3,1);
        printf("(%.2lf,%.2lf)\n",c.x,c.y);
    }
    return 0;
}

F题:

找规律/二进制

题目大意:给出a0到an-1,和一个表达式 (a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1)。给出q,求x^q的系数。

观察表达式,可以发现,给出n,可以构成x^0、x^1、x^2、……、x^(2^n-1)项,并且前面的系数就是将对应的指数化为二进制后,1所对应的系数之乘积。比如x^9的系数,把9化为二进制:1001,则对应的系数为a3*a0.

这样,对于给定的q,若大于2^n-1,则结果为0,否则将二进制位上对应为1的系数相乘即可。

感觉题中的数据有问题。。1<=ai<=100,n<=50,那么系数之乘积不会超过5000。。即使中间结果不取膜,也应该不会溢出。但中间不取膜就WA,取膜就过了。。


#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
typedef double db;
typedef long long LL;
#define mod 2012
int a[105];
int main()
{
    int t,Q,n,i;
    LL p;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(i=0;i<n;++i) cin>>a[i];
        cin>>Q;
        while(Q--)
        {
            cin>>p;
            LL ans=1;
            i=0;
            while(p)
            {
                if(i>n-1) {ans=0;break;}
                if(p&1) ans*=a[i];
                ++i;
                p>>=1;
                ans%=mod;
            }
            printf("%d\n",ans%mod);
        }
    }
    return 0;
}


I题:

简单的概率DP求期望。

题目大意:n层的三角形,第一层1个格子、第二层2个,以此类推。

先要从第一层走到最后一层的最左边的那个格子。求移动步数的期望。

已知:

1、若当前格子左边没有格子,则向左下、向右下移动的概率为a、b。a+b=1

2、当前格子下面没有格子了,则向左移动概率为1

3、左边有格子、下面也有格子,则向左下、向右下移动的概率为c、d,向左移动的概率为e。c+d+e=1


分析:

这类求期望的问题,通常都是设出到当前状态到目的地的期望,并从目标状态倒推回初始状态。

设dp[i][j]表示从坐标(i,j)到终点的移动步数期望。

我这里是设起点坐标为(1,1),终点坐标为(n,1)。

那么dp[n][1]=0。

然后可以递推出最后一行的期望。再由最后一行依次往上推即可。


#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
typedef double db;
db dp[50][50];
int main()
{
    int n,i,j;
    db a,b,c,d,e;
    while(cin>>n&&n)
    {
        cin>>a>>b>>c>>d>>e;
        memset(dp,0,sizeof(dp));
        for(i=2;i<=n;++i) dp[n][i]=dp[n][i-1]+1;
        for(i=n-1;i>=1;--i)
        {
            dp[i][1]=a*(dp[i+1][1]+1)+b*(dp[i+1][2]+1);
            for(j=2;j<=i;++j)
                dp[i][j]=e*(dp[i][j-1]+1)+c*(dp[i+1][j]+1)+d*(dp[i+1][j+1]+1);
        }
        printf("%.2lf\n",dp[1][1]);
    }
    return 0;
}







你可能感兴趣的:(2013山东省赛回顾A、F、I)