zoukankan      html  css  js  c++  java
  • Codeforces 193E

    Codeforces 题目传送门 & 洛谷题目传送门

    蠢蠢的我竟然第一眼想套通项公式?然鹅显然 (5)(mod 10^{13}) 意义下并没有二次剩余……我真是活回去了。。。

    考虑打表找规律(u1s1 这是一个非常有用的技巧,因为这个 (10^{13}) 给的就很灵性,用到类似的技巧的题目还有这个,通过对这些模数的循环节打表找出它们的共同性质,所以以后看到什么特殊的数据或者数据范围特别大但读入量 (mathcal O(1)) 的题(比如 CF838D)可以考虑小数据打几个表看看有没有什么共同特征,说不定对解题有些用处),斐波那契数列在模 (10,100,1000,10000,100000,cdots) 意义下的循环节恰好是 (60,300,1500,15000,150000),后面依次乘 (10)

    因此我们考虑这样一个算法,我们考虑枚举 (f_1,f_2,cdots,f_{1.5 imes 10^6}),即 Fibonacci 数列在模 (10^6) 下的循环节并求出满足 (f_iequiv npmod{10^6})(i) 组成的集合 (S),然后一步步将模数乘 (10) 并生成新的集合 (S),具体来说,由于每 (1.5 imes 10^6) 项斐波那契数列恰好构成一个循环节,因此斐波那契数列模 (10^7) 的一个循环节恰好由 (10) 个模 (10^6) 的循环节组成,因此在一个模 (10^7) 的循环节中,所有 (f_i)(n)(10^6) 同余的 (i) 一定可以写成 (kT+x) 的形式,其中 (k=0,1,2,cdots,9,T=1.5 imes 10^6,xin S),我们只需检验是否 (f_{kT+x}equiv npmod{10^7}) 即可求出 (f_iequiv npmod{10^7})(i) 组成的集合 (S),也就完成了由 (10^6 o 10^7) 的转化,如此一直推到 (10^{13}) 即可。

    时间复杂度 (mathcal O( ext{能过}))

    const int T=1.5e6;
    const ll MOD=1e13;
    const int SMOD=1e6;
    const ll INF=1e18;
    ll n;
    ll smul(ll x,ll y){
    	ll ret=0;
    	for(;y;y>>=1,(x<<=1)%=MOD) if(y&1) (ret+=x)%=MOD;
    	return ret;
    }
    struct mat{
    	ll a[2][2];
    	mat(){memset(a,0,sizeof(a));}
    	mat operator *(const mat &rhs){
    		mat ret;
    		for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++)
    			ret.a[i][j]+=smul(a[i][k],rhs.a[k][j]);
    		for(int i=0;i<2;i++) for(int j=0;j<2;j++) ret.a[i][j]%=MOD;
    		return ret;
    	}
    };
    ll getf(ll ps){
    	mat bs;bs.a[0][1]=bs.a[1][0]=bs.a[1][1]=1;
    	mat rs;rs.a[0][0]=rs.a[1][1]=1;
    	for(;ps;ps>>=1,bs=bs*bs) if(ps&1) rs=rs*bs;
    	return rs.a[1][0];
    }
    vector<ll> can,tmp;
    int main(){
    	scanf("%lld",&n);
    	for(ll i=1,p=0,q=1;i<=T;i++){
    		if(q%SMOD==n%SMOD) can.pb(i);
    		p=(p+q)%MOD;p^=q^=p^=q;
    	} ll CT=T,CMOD=SMOD;
    	while(CMOD^MOD){
    		tmp.clear();CMOD*=10;
    		for(ll x:can) for(int i=0;i<=9;i++)
    			if(getf(CT*i+x)%CMOD==n%CMOD) tmp.pb(CT*i+x);
    		swap(tmp,can);CT*=10;
    	} ll res=INF;for(ll x:can) chkmin(res,x);
    	printf("%lld
    ",(res==INF)?-1:res);
    	return 0;
    }
    
  • 相关阅读:
    tmux工具,终端复用
    使用sgdisk进行磁盘分区
    「Spring Boot 2.4 新特性」启动耗时详细监控
    「Spring Boot 2.4 新特性」启动耗时详细监控
    「SpringBoot2.4新特性」jar自动瘦身
    Spring Boot 2.4 新特性,全新的Cron表达式处理机制
    「Spring Boot 2.4 新特性」一键构建Docker镜像
    Spring Boot 接口幂等插件使用
    Druid 监控分布式解决方案
    Ehcache 入门详解 (转)
  • 原文地址:https://www.cnblogs.com/ET2006/p/Codeforces-193E.html
Copyright © 2011-2022 走看看