// Find the continued fraction representation of P/Q.autofraction(intp,intq){std::vector<int>a;while(q){a.push_back(p/q);std::tie(p,q)=std::make_pair(q,p%q);}returna;}
1234567
# Find the continued fraction representation of P/Q.deffraction(p,q):a=[]whileq:a.append(p//q)p,q=q,p%qreturna
// Find the convergents of a continued fraction A.// Numerators and denominators stored separately in P and Q.autoconvergents(std::vector<int>a){std::vector<int>p={0,1};std::vector<int>q={1,0};for(autoit:a){p.push_back(p.back()*it+p.end()[-2]);q.push_back(q.back()*it+q.end()[-2]);}returnstd::make_pair(p,q);}
123456789
# Find the convergents of a continued fraction A.# Numerators and denominators stored separately in P and Q.defconvergents(a):p=[0,1]q=[1,0]foritina:p.append(p[-1]*it+p[-2])q.append(q[-1]*it+q[-2])returnp,q
// Return (x,y) such that Ax+By=C.// Assume that such (x,y) exists.autodio(intA,intB,intC){std::vector<int>p,q;std::tie(p,q)=convergents(fraction(A,B));C/=A/p.back();intt=p.size()%2?-1:1;returnstd::make_pair(t*C*q.end()[-2],-t*C*p.end()[-2]);}
1234567
# Return (x, y) such that Ax+By=C.# Assume that such (x, y) exists.defdio(A,B,C):p,q=convergents(fraction(A,B))C//=A//p[-1]# divide by gcd(A, B)t=(-1)iflen(p)%2else1returnt*C*q[-2],-t*C*p[-2]
// Expand [..., n] to [..., n-1, 1] if needed.voidexpand(std::vector<int>&a){if(a.size()==1||a.back()>1){--a.back();a.push_back(1);}}// Check if a is smaller than b.boolless_than(std::vector<int>a,std::vector<int>b){expand(a);expand(b);for(inti=0;i<a.size()-1||i<b.size()-1;++i){intd=(i<a.size()-1?a[i]:0)-(i<b.size()-1?b[i]:0);if(i&1)d=-d;if(d<0){returntrue;}elseif(d>0){returnfalse;}}returnfalse;}
1 2 3 4 5 6 7 8 9101112131415
# Expand [..., n] to [..., n-1, 1] if needed.defexpand(a):ifa[-1]!=1orlen(a)==1:a[-1]-=1a.append(1)returna# Check if a is smaller than b.defless_than(a,b):a=expand(a)b=expand(b)a=[(-1)**i*a[i]foriinrange(len(a))]b=[(-1)**i*b[i]foriinrange(len(b))]returna<b
// Get X +- EPSILON.autopm_eps(std::vector<int>a){constexprintinf=0x3f3f3f3f;// Deal with empty continued fraction for 1/0.if(a.empty()){a.emplace_back(inf);}autob=a;expand(b);a.emplace_back(inf);b.emplace_back(inf);returnless_than(a,b)?std::make_pair(a,b):std::make_pair(b,a);}// Find the lexicographically smallest (q, p)// such that p0/q0 < p/q < p1/q1.automiddle(intp0,intq0,intp1,intq1){autoa0=pm_eps(fraction(p0,q0)).second;autoa1=pm_eps(fraction(p1,q1)).first;std::vector<int>a;for(inti=0;i<a0.size()||i<a1.size();++i){if(a0[i]==a1[i]){a.emplace_back(a0[i]);}else{a.emplace_back(std::min(a0[i],a1[i])+1);break;}}autopq=convergents(a);returnstd::make_pair(pq.first.back(),pq.second.back());}
1 2 3 4 5 6 7 8 910111213141516171819202122232425
# Get X +- EPSILON.defpm_eps(a):# Deal with empty continued fraction for 1/0.ifnota:a.append(float("inf"))b=expand(a.copy())a.append(float("inf"))b.append(float("inf"))return(a,b)ifless_than(a,b)else(b,a)# Find the lexicographically smallest (q, p)# such that p0/q0 < p/q < p1/q1.defmiddle(p0,q0,p1,q1):a0=pm_eps(fraction(p0,q0))[1]a1=pm_eps(fraction(p1,q1))[0]a=[]foriinrange(min(len(a0),len(a1))):ifa0[i]==a1[i]:a.append(a0[i])else:a.append(int(min(a0[i],a1[i]))+1)breakp,q=convergents(a)returnp[-1],q[-1]
#include<algorithm>#include<iostream>#include<tuple>#include<vector>constexprintM=1e9+7;// FLTs. Essentially 2x2 matrix.structFracLinearTrans{intmat[4];FracLinearTrans():mat{}{}FracLinearTrans(intx):mat{x,1,1,0}{}FracLinearTrans(inta,intb,intc,intd):mat{a,b,c,d}{}FracLinearTransoperator*(constFracLinearTrans&rhs)const{returnFracLinearTrans(((longlong)mat[0]*rhs.mat[0]+(longlong)mat[1]*rhs.mat[2])%M,((longlong)mat[0]*rhs.mat[1]+(longlong)mat[1]*rhs.mat[3])%M,((longlong)mat[2]*rhs.mat[0]+(longlong)mat[3]*rhs.mat[2])%M,((longlong)mat[2]*rhs.mat[1]+(longlong)mat[3]*rhs.mat[3])%M);}FracLinearTransinv()const{returnFracLinearTrans(mat[3],M-mat[1],M-mat[2],mat[0]);}};intmain(){intn,q;std::cin>>n>>q;// Get prefix sum of FLTs.std::vector<FracLinearTrans>ps(1,{1,0,0,1});ps.reserve(n+1);for(inti=1;i<=n;++i){inta;std::cin>>a;ps[i]=ps[i-1]*FracLinearTrans(a);}// Query.for(;q;--q){intl,r;std::cin>>l>>r;// Difference.autores=ps[l-1].inv()*ps[r];intu=res.mat[0],d=res.mat[2];// Correct signs.if(!(l&1)){if(u)u=M-u;if(d)d=M-d;}printf("%d %d\n",u,d);}return0;}
# PYTHON IS TOO SLOW TO PASS THIS PROBLEM.# JUST FOR REFERENCE.M=10**9+7defmul(a,b):return((a[0]*b[0]+a[1]*b[2])%M,(a[0]*b[1]+a[1]*b[3])%M,(a[2]*b[0]+a[3]*b[2])%M,(a[2]*b[1]+a[3]*b[3])%M,)