题意:
一只熊从(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;
}