CodeForces 385E Bear in the Field

题意:

一只熊从(sx,sy)开始走  速度为(dx,dy)  每一秒钟速度的两个维度同时加上所在坐标的和(即 +x+y)然后走一步

求  T秒钟后熊站在哪


思路:

T无比的大不可能是暴力的  于是想到两个可能

一是这个路径有循环有规律可以排除好多步

二是能构造出一个表示他行为的矩阵用快速幂做

由于规律很难找到  所以可以列一下他的状态变化  (x,y,dx,dy,i) 表示i时刻熊站在(x,y)处速度向量(dx,dy)

它的下一个状态是 ( 2x+y+dx+i , x+2y+dy+i , x+y+dx , x+y+dy , i+1 )  根据此构造矩阵

为了方便可以把平面从(1,1)平移到(0,0)  这时速度需要+2 (因为速度每次+x+y  x和y都-1则速度都+2)

所以我的矩阵对应常数的地方为2  之所以敢改动矩阵是因为F与fzc乘一次后除了第一列其余全是0

详见代码


其实我的思路不是很好  有队友master的帮助才搞定了这题…

http://kmjp.hatenablog.jp/entry/2014/01/25/1000  这份题解思路简单些  不过是日语的要用翻译软件


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef __int64 uint64;

const int mat_n=6;
uint64 n,sx,sy,dx,dy,t;
uint64 fzc[6][6];
uint64 F[6][6]={
    {2,1,1,0,1,2},
    {1,2,0,1,1,2},
    {1,1,1,0,1,2},
    {1,1,0,1,1,2},
    {0,0,0,0,1,1},
    {0,0,0,0,0,1}
};

void matrix_mul(uint64 a[][mat_n],uint64 b[][mat_n],uint64 mod)
{
    uint64 c[mat_n][mat_n];
    int i,j,k;
    for(i=0;i<mat_n;i++)
    {
        for(j=0;j<mat_n;j++)
        {
            c[i][j]=0;
            for(k=0;k<mat_n;k++)
            {
                c[i][j]=(c[i][j]+(a[i][k]*b[k][j])%mod)%mod;
            }
        }
    }
 
    for(i=0;i<mat_n;i++)
        for(j=0;j<mat_n;j++)
            a[i][j]=c[i][j];
}

void matrix_power(uint64 s[][mat_n],uint64 k,uint64 mod)
{
    uint64 ans[mat_n][mat_n];
    memset(ans,0,sizeof(ans));
    int i,j;
    for(i=0;i<mat_n;i++)
        ans[i][i]=1;

    while(k>0)
    {
        if(k%2==1) matrix_mul(ans,s,mod);
        k=k/2;
        matrix_mul(s,s,mod);
    }

    for(i=0;i<mat_n;i++)
        for(j=0;j<mat_n;j++)
            s[i][j]=ans[i][j];
}

int main()
{
    scanf("%I64d %I64d %I64d %I64d %I64d %I64d",&n,&sx,&sy,&dx,&dy,&t);
    sx--; sy--;
    fzc[0][0]=sx; fzc[1][0]=sy; fzc[2][0]=dx; fzc[3][0]=dy; fzc[4][0]=0; fzc[5][0]=1;
    matrix_power(F,t,n);
    matrix_mul(F,fzc,n);
    printf("%I64d %I64d\n",(F[0][0]+n)%n+1,(F[1][0]+n)%n+1);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值