题目链接:
http://acm.zju.edu.cn/changsha/showContestProblem.do?problemId=19
题目意思:
题目很晦涩。在k维空间,开始长度为l,操作一次变为l+√(l*(l+1)).问最后%k还剩下的整数是多少。
解题思路:
数学公式+矩阵快速幂。
因为是在k维空间,所以也就是要求(l+√(l*(l-1))^k向下取整后%k的值。
这题和今年长沙邀请赛的A题,差不多,只不过那题是向上取整,这题是向下取整,减一就行了。
思路参考hdu 4565
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define Maxn 3
ll m,a,b;
struct Mar
{
int r,c;
ll sa[Maxn][Maxn];
void init(int a,int b)
{
r=a,c=b;
memset(sa,0,sizeof(sa));
}
};
Mar operator *(struct Mar & a,struct Mar & b)
{
Mar c;
c.init(a.r,b.c);
for(int k=1;k<=a.c;k++)
{
for(int i=1;i<=c.r;i++)
{
if(!a.sa[i][k])
continue;
for(int j=1;j<=c.c;j++)
{
if(!b.sa[k][j])
continue;
c.sa[i][j]=(c.sa[i][j]+a.sa[i][k]*b.sa[k][j])%m;
}
}
}
return c;
}
Mar ba[35],ans;
void init()
{
ba[0].init(2,2);
ba[0].sa[1][1]=(2*a)%m,ba[0].sa[1][2]=((b-a*a)%m+m)%m;
ba[0].sa[2][1]=1,ba[0].sa[2][2]=0;
for(int i=1;i<32;i++) //2^i
{
ba[i]=ba[i-1]*ba[i-1];
}
}
int main()
{
ll l,k;
while(~scanf("%lld%lld",&k,&l))
{
a=l,b=l*(l-1);
m=k;
init();
ans.init(2,1);
ans.sa[1][1]=(2*a)%m,ans.sa[2][1]=2;
for(int i=0;i<32&&k;i++)
{
if(k&1)
{
ans=ba[i]*ans;
}
k>>=1;
}
printf("%lld\n",(ans.sa[2][1]-1+m)%m);
}
return 0;
}