本文主要是介绍[CF1106F]Lunar New Year and a Recursive Sequence,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Lunar New Year and a Recursive Sequence
题解
忽的发现这题难度只有2400,还是我数学太菜了
如果像原式那样对整个式子每次都进行次方的更新的话,明显会T掉,我们可以对它的幂进行更新,因为做出贡献的项只有这一个,每个都可以只用表示出来。
设为的次方,可得,可如果暴力转移的话级别的明显会让我们T掉。
发现这个式子很容易用矩阵乘法实现转换,矩阵乘法就可以被定义为
由与两矩阵相乘来进行转换。
这样来进行转换。这样,第n项的指数就是时的第项了。
因为这是求的次数,所以必须模。
由于。由于的原根为,所以肯定有。
原式也可以被表示为。
接下来我们可以用BSGS求出的值,用乘法逆元将这个消去,就可以得到的取值。答案即为。
于是就可以用的时间复杂度求出答案了。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
typedef long long LL;
#define int LL
#define MAXN 500005
const double eps=1e-7;
const int INF=0x7f7f7f7f;
const LL mo=998244353;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
int qkpow(int a,int s){int t=1;while(s){if(s&1)t=1ll*a*t%mo;a=1ll*a*a%mo;s>>=1;}return t;
}
int add(int x,int y){return x+y>=mo-1?x+y-mo+1:x+y;}
int K;
struct matrix{int c[105][105];matrix(){memset(c,0,sizeof(c));}friend matrix operator * (const matrix &a,const matrix &b){matrix res;for(int i=1;i<=K;i++)for(int k=1;k<=K;k++)if(a.c[i][k])for(int j=1;j<=K;j++) res.c[i][j]=add(res.c[i][j],1ll*a.c[i][k]*b.c[k][j]%(mo-1));return res;}
}A,B,C;
matrix mat_qkpow(matrix a,int s){matrix t;for(int i=1;i<=K;i++)t.c[i][i]=1;while(s){if(s&1)t=a*t;a=a*a;s>>=1;} return t;
}
map<int,int>mp;
int bsgs(LL p,int b,int n){int tmp=1,sum=1,m=ceil(sqrt(p));mp[n%p]=0;for(int i=1;i<=m;i++)tmp=1ll*tmp*b%p,mp[1ll*tmp*n%p]=i;for(int j=1;j<=m;j++){sum=1ll*sum*tmp%p;if(mp[sum])return j*m-mp[sum];}return -1;
}
int exgcd(int a,int b,int &x,int &y){if(!b){x=1;y=0;return a;}int d=exgcd(b,a%b,y,x);y-=x*(a/b);return d;
}
signed main(){read(K);A.c[1][K]=1;for(int i=K;i>0;i--)read(B.c[i][K]);for(int i=2;i<=K;i++)B.c[i][i-1]=1;int n,m;read(n);read(m);C=A*mat_qkpow(B,n-1);int t=bsgs(mo,3,m);if(t==-1){puts("-1");return 0;}int x,y,d=exgcd(C.c[1][1],mo-1,x,y);if(t%d){puts("-1");return 0;}x=(t/d*x%(mo-1)+mo-1)%(mo-1);printf("%lld\n",qkpow(3,x));return 0;
}
谢谢!!!
---updata by 2020.10.5---
再做一遍感觉那个乘法逆元好难调,注意不能因为两者互质就直接没有乘法逆元。
这篇关于[CF1106F]Lunar New Year and a Recursive Sequence的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!