The Nth Iteam

题意:F(0)=1,F(1)=1,F(n)=3*F(n-1)+2*F(n-2) (n>=2) ,F(n) mod 998244353。给出Q跟N1,Ni=Ni-1^(F(Ni-1)*F(Ni-1)),求F(N1)^F(N2)^...^F(NQ

这个比赛的E跟H数据都水得很,但题还是不错的。

比赛时是求了个循环节,又进行了矩阵的降幂,然后本地+测试在时限内跑出了几组1e7的数据,才敢交的,但没想到数据那么水,矩阵快速幂+map记忆化一下就能过。

 #include<cstdio>
#include<tr1/unordered_map>
using namespace std;
typedef long long ll;
const int N=1e7+,md=;
tr1::unordered_map<ll,int> mmp;
ll aa[N],f[N];
struct Matrix{
int r,c;
ll a[][];
Matrix(){}
Matrix(int r,int c):r(r),c(c){
for(int i=;i<r;i++)
for(int j=;j<c;j++) a[i][j]=;
}
};
Matrix mmul(Matrix m1,Matrix m2,ll z){
Matrix ans(m1.r,m2.c);
for(int i=;i<m1.r;i++)
for(int j=;j<m2.c;j++)
for(int k=;k<m1.c;k++){
ans.a[i][j]+=m1.a[i][k]*m2.a[k][j]%z;
if(ans.a[i][j]>=z) ans.a[i][j]-=z;
}
return ans;
}
Matrix mpow(Matrix m1,ll y,ll z){
Matrix ans(m1.r,m1.c);
for(int i=;i<ans.r;i++) ans.a[i][i]=;
while(y){
if(y&) ans=mmul(ans,m1,z);
m1=mmul(m1,m1,z);
y>>=;
}
return ans;
} int main(){
f[]=;f[]=;
for(int i=;i<N;i++) f[i]=(f[i-]*3ll%md+f[i-]*2ll%md)%md;
int q,pos1,pos2,len,num,yu;
ll n,m,ans;
while(~scanf("%d%lld",&q,&n)){
ans=aa[]=;
mmp.clear();
pos1=pos2=-;
for(int i=;i<=q;i++){
if(n<N) aa[i]=f[n];
else{
m=n-;
if(m>=md-) m%=md-;
Matrix A(,),T(,);
A.a[][]=;
T.a[][]=;T.a[][]=;T.a[][]=;
T=mpow(T,m,md);
A=mmul(T,A,md);
aa[i]=A.a[][];
}
if(n==) break;
if(mmp[n]){
pos1=mmp[n];
pos2=i;
break;
}
else mmp[n]=i;
ans^=aa[i];
n=n^(aa[i]*aa[i]);
aa[i]^=aa[i-];
}
if(pos1!=-){
len=pos2-pos1;
num=(q-pos2+)/len;
yu=(q-pos2+)%len;
if(num&) ans^=aa[pos2-]^aa[pos1-];
if(yu) ans^=aa[pos1+yu-]^aa[pos1-];
}
printf("%lld\n",ans);
}
return ;
}

不应该过呀

但其实自己想一下,Q等于1e7,中间再套log的话,还有算矩阵快速幂时的一些常数,很明显就会T掉,水过去之余还是来学一些O(1)的处理方法。

首先这个数列显然是个线性递推数列,那么我们就可以求它的一个通项公式,具体求法360百科有好几个,我直接学习了第一个,方法:利用特征方程(线性代数解法)的解法。

下面是斐波那契数列通项公式的求解过程,我们依照此来求:

特征方程的概述

一个数列:X(n+2)=C1X(n+1)+C2Xn

设r,s使X(n+2)-rX(n+1)=s[X(n+1)-rXn]

所以X(n+2)=(s+r)X(n+1)-srXn

C1=s+r

C2=-sr

消去s就导出特征方程式 r*r-C1*r-C2=0

我们把C1=3,C2=2代入就有可以解除r=(3+√17)/2,s=(3-√17)/2

然后F(n)=x1*rn+x2*sn,我们把F(0)=0,F(1)=1,代入就能解得x1=1/√17,x2=-1/√17

那么上诉数列的通项公式就是F(n)=1/√17*(((3+√17)/2)n-((3-√17)/2)n)

这个解法包含不少线性代数的知识,不明白的可以去学一下那个待定系数等比数列求法,或者看一下这个斐波那契数列通项公式是怎样推导出来的?,里面有矩阵的推导过程。

回到这题,我们有了通项公式,√17的话,前面的博客就有讲到二次剩余,那么通过x2≡17(mod 998244353)可以求出x来代替√17,然后里面的除法我们可以求逆元,这些都可以先求出了。

相关代码如下:

 #include<cstdio>
#include<ctime>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int md=;
typedef long long ll;
struct Fp2{
ll x,y;
};
ll w;
Fp2 fmul(const Fp2 &f1,const Fp2 &f2){
Fp2 ans;
ans.x=(f1.x*f2.x%md+f1.y*f2.y%md*w%md)%md;
ans.y=(f1.x*f2.y%md+f1.y*f2.x%md)%md;
return ans;
}
Fp2 fpow(Fp2 x,ll y){
Fp2 ans;
ans.x=;ans.y=;
while(y){
if(y&) ans=fmul(ans,x);
x=fmul(x,x);
y>>=;
}
return ans;
}
ll poww(ll x,ll y){
ll ans=;
while(y){
if(y&){
ans*=x;
if(ans>=md) ans%=md;
}
x*=x;
if(x>=md) x%=md;
y>>=;
}
return ans;
}
ll cipolla(ll x){
if(x==) return ;
if(x==) return ;
if(poww(x,(md-)>>)+==md) return -;
ll a;
while(true){
a=rand()%md;
w=((a*a%md-x)%md+md)%md;
if(poww(w,(md-)>>)+==md) break;
}
Fp2 ans;
ans.x=a;ans.y=;
ans=fpow(ans,(md+)>>);
return ans.x;
}
int main(){
srand(time(NULL));
ll py17=cipolla(),nv2=poww(,md-);
printf("根号17的二次剩余:%lld\n",py17);
printf("2的逆元:%lld\n",nv2);
printf("根号17的二次剩余的逆元:%lld\n",poww(py17,md-));
printf("3+根号7除2:%lld\n",((+py17)%md*nv2%md)%md);
printf("3-根号7除2:%lld\n",(((-py17)%md+md)%md*nv2%md)%md);
return ;
}

打表鸭

其中一组结果:

那么这时,我们设aa=736044383,bb=262199973,我们快速幂就可以log求出F(n)

但这还不够,我们需要的是O(1),所以我们可以先分块预处理。

怎么做呢,这时的aa,bb在 mod 998244353的意义下,已经是整数了,所以求aan或者bbn在n很大时,就可以进行我们前面指数循环节里的欧拉降幂了,也就是n=n%998244352+998244352(998244352是998244353是欧拉函数)

这时n最大是1996488703,√1996488703=44682.084810357719028060186400879,那么我们可以把5e4(大于等于44683都可以)为一组分块,这样我们先预处理出aa跟bb的0次幂,1次幂,到5e4次幂,然后再预处理0*5e4次幂,1*5e4次幂到5e4*5e4次幂

那么当我们要求aa或者bb的n次幂时其实就是求(n/5e4)(整除)*5e4次幂 * n%5e4次幂,也就是设N=5e4,那么 n=q*N+r,q=n/N,r=n%N

这样我们就可以在O(1)求出相应的F(n),

 #include<cstdio>
typedef long long ll;
const int N=5e4,md=;
const ll nv17=,aa=,bb=;
typedef long long ll;
ll a[N+],af[N+],b[N+],bf[N+];
void init(){
a[]=b[]=;
for(int i=;i<=N;i++){
a[i]=a[i-]*aa;
if(a[i]>=md) a[i]%=md;
b[i]=b[i-]*bb;
if(b[i]>=md) b[i]%=md;
}
af[]=bf[]=;
for(int i=;i<=N;i++){
af[i]=af[i-]*a[N];
if(af[i]>=md) af[i]%=md;
bf[i]=bf[i-]*b[N];
if(bf[i]>=md) bf[i]%=md;
}
}
int main(){
init();
int q;
ll n;
while(~scanf("%d%lld",&q,&n)){
ll ans=,fn,m;
while(q--){
if(n==) break;
m=n;
if(m>=md-) m=m%(md-)+(md-);
fn=((af[m/N]*a[m%N])%md)-((bf[m/N]*b[m%N])%md);
fn=(fn%md+md)%md;
fn*=nv17;
if(fn>=md) fn%=md;
ans^=fn;
n=n^(fn*fn);
}
printf("%lld\n",ans);
}
return ;
}

嘤嘤嘤

但由于数据的问题,预处理在计蒜客上实际运行时间还没直接套矩阵快速幂的快,自己出几个大数据就可看出哪个更快了,但我们不要被数据影响了,学到东西才是关键了。

总的来说,这题涉及到了线性递推数列的通项公式,二次剩余,逆元,还有分块思想,是个很不错的题。

2019 南昌ICPC网络赛H The Nth Item的更多相关文章

  1. 南昌网络赛 H The Nth Item

    南昌网络赛The Nth Item 暴力快速幂+unordered_map记忆化 注意:记忆化不能写到快速幂求解函数里,不断调用函数会造成很大的时间浪费 #include<bits/stdc++ ...

  2. 2019南昌网络赛H The Nth Item(打表找询问循环节 or 分段打表)

    https://nanti.jisuanke.com/t/41355 思路 从fib循环节入手,\(O(1e7log(1e9))\),tle 因为只需要输出所有询问亦或后的结果,所以考虑答案的循环节, ...

  3. 2019南昌网络赛H The Nth Item(二阶线性数列递推 + 广义斐波那契循环节 + 分段打表)题解

    题意: 传送门 已知\(F(n)=3F(n-1)+2F(n-2) \mod 998244353,F(0)=0,F(1)=1\),给出初始的\(n_1\)和询问次数\(q\),设每一次的答案\(a_i= ...

  4. 2019沈阳icpc网络赛H德州扑克

    题面:https://nanti.jisuanke.com/t/41408 题意:A,2,3,4,5,6,7,8,9,10,J,Q,K,13张牌,无花色之分,val为1~13. 给n个人名+n个牌,输 ...

  5. 2019-ACM-ICPC-南昌区网络赛-H. The Nth Item-特征根法求通项公式+二次剩余+欧拉降幂

    2019-ACM-ICPC-南昌区网络赛-H. The Nth Item-特征根法求通项公式+二次剩余+欧拉降幂 [Problem Description] ​ 已知\(f(n)=3\cdot f(n ...

  6. POJ-2796 & 2019南昌邀请赛网络赛 I. 区间最大min*sum

    http://poj.org/problem?id=2796 https://nanti.jisuanke.com/t/38228 背景 给定一个序列,对于任意区间,min表示区间中最小的数,sum表 ...

  7. 计蒜客 2019南昌邀请网络赛J Distance on the tree(主席树)题解

    题意:给出一棵树,给出每条边的权值,现在给出m个询问,要你每次输出u~v的最短路径中,边权 <= k 的边有几条 思路:当时网络赛的时候没学过主席树,现在补上.先树上建主席树,然后把边权交给子节 ...

  8. 2019南昌邀请赛网络赛:J distance on the tree

    1000ms 262144K   DSM(Data Structure Master) once learned about tree when he was preparing for NOIP(N ...

  9. 2019 徐州icpc网络赛 E. XKC's basketball team

    题库链接: https://nanti.jisuanke.com/t/41387 题目大意 给定n个数,与一个数m,求ai右边最后一个至少比ai大m的数与这个数之间有多少个数 思路 对于每一个数,利用 ...

随机推荐

  1. POJ 1015 Jury Compromise (记录路径的背包问题)

    (点击此处查看原题) 题意 为了审判某一个人,需要在n个人当中选出m个人组成陪审团,n个人中每个人都有作为起诉方的价值p和作为辩护方的价值d,为了保证公平性,要求m个人作为起诉方的价值之和P和作为辩护 ...

  2. 最新精仿Chinaz中国站长网整站源码带全部数据带采集功能

    用范围: 站长网源码演示地址:php源码运行环境:  phpChinaz站长网对于广大站长来说,是不会陌生的,现在几乎成为了每个站长都必须上的网站了.这次分享的是Chinaz站长网的源码,包含了chi ...

  3. springboot service dockerfile

    FROM java:8u111 MAINTAINER ianthony7@163.com # 定义变量 ENV WORK_DIR /opt ENV LOG_DIR /data/logs EXPOSE ...

  4. 计算机概论 64bit和32bit的CPU的不同

    32位(WOW32).64位(WOW64,x64)指的是两种不同的CPU架构. 32位的CPU能够在每个时钟周期传输32位数据,而64位的CPU能够在每个时钟周期传输64位数据. 32位系统可以访问2 ...

  5. 谈谈对Spring IOC的理解(转发)

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  6. ASP.NET Core中间件实现分布式 Session(转载)

    ASP.NET Core中间件实现分布式 Session 1. ASP.NET Core中间件详解 1.1. 中间件原理 1.1.1. 什么是中间件 1.1.2. 中间件执行过程 1.1.3. 中间件 ...

  7. 一个jenkins的bug

    部署在redhat上docker中的jenkins运行了很久了,最新发现一个站点不是最新的,于是去查看发现git仓库都连不上,我换成外网github的仓库就可以连非得是https吗???? 提示是域名 ...

  8. win10 增加一个新磁盘

    1.右键我的电脑,选择管理 可以看到C盘的空间相比较大,拿出来250G的空间做成E盘 2.选择OS(C:),右键,压缩卷,请稍后,点击压缩 3.此刻会看到,有一块黑色区域就是新建的未分配空间,这时我们 ...

  9. JavaSpring【三、Bean】

    配置项 id bean的标识 class bean的类全名 scope bean的作用域 constructor-arg 构造注入 properties 设值注入 autowire 装配模式 lazy ...

  10. 2.06_Python网络爬虫_正则表达式

    一:爬虫的四个主要步骤 明确目标 (要知道你准备在哪个范围或者网站去搜索) 爬 (将所有的网站的内容全部爬下来) 取 (过滤和匹配我们需要的数据,去掉没用的数据) 处理数据(按照我们想要的方式存储和使 ...