zoukankan      html  css  js  c++  java
  • agc015F Kenus the Ancient Greek

    题意:

    有$Q$次询问,每次给定$X_i$和$Y_i$,求对于$1leq x leq X_i , 1 leq y leq Y_i$,$(x,y)$进行辗转相除法的步数的最大值以及取到最大值的方案数。

    步数定义如下:
    $(a,b)$和$(b,a)$步数相同;
    $(0,a)$步数为0;
    如果$a leq b$,$(a,b)$的步数为$(b \% a,a)$的步数+1。

    $Q leq 3*10^5 , X_i,Y_i leq 10^{18}$。

    这种题我一看就懵了,明显要推什么结论,但是我怎么才能想到这和斐波那契数列有关呢?

    atcoder的官方题解挂了,耗费了我2h去思考自己是英语太撇了还是太弱了

    我们定义$f(a,b)$为$(a,b)$辗转相除的步数。对于斐波那契数列,我们规定$F[0]=F[1]=1$

    首先,我们可以用归纳法证明结论,$f(F[i],F[i+1])=i$,并且如果有$f(x,y)=i (x<y)$,那么$x geq F[i] , y geq F[i+1]$

    定义一个数对$(x,y)$是好的,当且仅当不存在$x'<x , y'<y$的$(x',y')$满足 $f(x',y')>f(x,y)$,我们发现只有好的数对才对答案有贡献

    定义一个数对$(x,y)$是优秀的,若$f(x,y)=k$,那么$x,y leq F[k+2]+F[k-1]$

    我们可以得到一个结论:好的数对$(x,y)$经过一次辗转相除之后,一定得到一个优秀的数对

    用反证法证明这个结论,对于一个数对$(x,y)$,$f(x,y)=k$,令$x<y$,若$y>F[k+2]+F[k-1]$:

    因为$f(x,y)=k$,所以$x geq F[k]$

    所以如果一个好的数对$(a,b)=(y,py+x) , f(a,b)=k+1$,辗转相除之后得到$(x,y)$,那么

    $a=y > F[k+2] , b=py+x geq y+x > F[k+2]+F[k-1]+F[k] = F[k+3]$

    所以存在$x'=F[k+2],y'=F[k+3]$,满足$f(x',y')>f(a,b)$。

    然后我们可以用递推的思路,根据$f(x,y)=k$的优秀数对推出$f(x,y)=k+1$的优秀数对

    优秀的数对并不多,而且每次推的时候只会多那么一两个的样子,所以可以直接预处理。

    最后再根据优秀数对来算好的数对的数量就可以了。

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<vector>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=100+7,W=90;
    const ll mod=1e9+7;
    ll Td,n,m,ans,sum,f[maxn];
    
    char cc;ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;ff=1; cc=getchar();
    	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    struct Node{
    	ll x,y;
    	Node(){}
    	Node(ll x,ll y):x(x),y(y){}
    }o;
    vector<Node> G[maxn];
    
    int main() {
    	ll x,y,s; f[0]=f[1]=1;
    	For(i,2,W) f[i]=f[i-1]+f[i-2];
    	G[1].push_back(Node(1,2)); G[1].push_back(Node(1,3));
    	G[1].push_back(Node(1,4));
    	For(i,1,W-3) {
    		s=G[i].size();
    		For(j,0,s-1) {
    			o=G[i][j]; x=o.y; y=o.x+x;
    			while(y<=f[i+3]+f[i]) {
    				G[i+1].push_back(Node(x,y));
    				y+=x;
    			}
    		}
    	}
    	
    	read(Td);
    	while(Td--) {
    		read(n); read(m);
    		if(n>m) swap(n,m);
    		for(ans=1;f[ans+1]<=n&&f[ans+2]<=m;++ans) ;
    		printf("%lld ",ans);
    		if(ans==1) {
    			printf("%lld
    ",n*m%mod);
    			continue;
    		}
    		s=G[ans-1].size(); sum=0;
    		For(i,0,s-1) {
    			o=G[ans-1][i]; x=o.x; y=o.y;
    			if(y<=n) sum+=(m-x)/y%mod;
    			if(y<=m) sum+=(n-x)/y%mod;
    			sum%=mod;
    		}
    		printf("%lld
    ",sum);
    	}
    	return 0;
    }
    
  • 相关阅读:
    [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树
    [BZOJ3230] 相似字串 后缀数组+RMQ
    [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树
    [BZOJ4044]Virus synthesis 回文自动机的DP
    [BZOJ2055]80人环游世界 有上下界最小费用最大流
    [BZOJ2502]清理雪道 有上下界网络流(最小流)
    [BZOJ2095][Poi2010]Bridges 最大流(混合图欧拉回路)
    [BZOJ2288&BZOJ1150]一类堆+链表+贪心问题
    [BZOJ4820]硬币游戏 KMP+高斯消元
    [BZOJ1559]密码 AC自动机+状压
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/9092381.html
Copyright © 2011-2022 走看看