【LOJ】#138. 类欧几里得算法

传送门:loj138


题解

被标题坑进去,断断续续做了一天。。。确实是“类欧几里得算法”啊(雾。。。

原题解-fjzzq2002

设答案为函数 f ( a , b , c , n , k 1 , k 2 ) = ∑ i = 0 n i k 1 ⌊ a i + b c ⌋ k 2 f(a,b,c,n,k_1,k_2)=\sum\limits_{i=0}^ni^{k_1}\lfloor\dfrac{ai+b}{c}\rfloor^{k_2} f(a,b,c,n,k1,k2)=i=0nik1cai+bk2

考虑以下情况:

  • ⌊ a i + b c ⌋ \lfloor\dfrac{ai+b}{c}\rfloor cai+b为常量( a = 0 a=0 a=0 ⌊ a n + b c ⌋ = 0 \lfloor\dfrac{an+b}{c}\rfloor=0 can+b=0),直接拉格朗日插值算出 ∑ i = 0 n i k 1 \sum\limits_{i=0}^ni^{k_1} i=0nik1即可。

  • a ≥ c a\geq c ac b ≥ c b\geq c bc f ( a , b , c , n , k 1 , k 2 ) = ∑ i = 0 n i k 1 ( ⌊ a c ⌋ ⋅ i + ⌊ b c ⌋ + ⌊ i ⋅ ( a % c ) + b % c c ⌋ ) k 2 f(a,b,c,n,k_1,k_2)=\sum\limits_{i=0}^ni^{k_1}(\lfloor\dfrac{a}{c}\rfloor·i+\lfloor\dfrac{b}{c}\rfloor+\lfloor\dfrac{i·(a\%c)+b\%c}{c}\rfloor)^{k_2} f(a,b,c,n,k1,k2)=i=0nik1(cai+cb+ci(a%c)+b%c)k2,二项式展开一下得到若干 λ ∑ i = 0 n i k 1 ( ⌊ i ⋅ ( a % c ) + b % c c ⌋ ) k 2 \lambda\sum\limits_{i=0}^n i^{k_1} (\lfloor\dfrac{i·(a\%c)+b\%c}{c}\rfloor)^{k_2} λi=0nik1(ci(a%c)+b%c)k2,迭代求解 f ( a % c , b % c , n , k 1 , k 2 ) f(a\%c,b\%c,n,k_1,k_2) f(a%c,b%c,n,k1,k2)即可。

  • 不满足上面两种情况( a < c , b < c a<c,b<c a<c,b<c),把 i k 2 i^{k_2} ik2转成 ∑ j = 0 i − 1 ( j + 1 ) k 2 − j k 2 \sum\limits_{j=0}^{i-1}(j+1)^{k_2}-j^{k_2} j=0i1(j+1)k2jk2(设 0 k 2 = 0 0^{k_2}=0 0k2=0)。
    m = ⌊ a n + b c ⌋ > 0 m=\lfloor\dfrac{an+b}{c}\rfloor>0 m=can+b>0,则
      f ( a , b , c , n , k 1 , k 2 ) \ \quad f(a,b,c,n,k_1,k_2)  f(a,b,c,n,k1,k2)
    = ∑ t = 0 m − 1 ( ( t + 1 ) k 2 − t k 2 ) ∑ i = 0 n i k 1 [ ⌊ a i + b c ⌋ ≥ t + 1 ] =\sum\limits_{t=0}^{m-1}((t+1)^{k_2}-t^{k_2})\sum\limits_{i=0}^ni^{k_1}[\lfloor\dfrac{ai+b}{c}\rfloor\geq t+1] =t=0m1((t+1)k2tk2)i=0nik1[cai+bt+1]
    = ∑ t = 0 m − 1 ( ( t + 1 ) k 2 − t k 2 ) ∑ i = 0 n i k 1 [ i > ⌊ t c + c − b − 1 a ⌋ ] =\sum\limits_{t=0}^{m-1}((t+1)^{k_2}-t^{k_2})\sum\limits_{i=0}^ni^{k_1}[i> \lfloor\dfrac{tc+c-b-1}{a}\rfloor] =t=0m1((t+1)k2tk2)i=0nik1[i>atc+cb1]
    = ∑ t = 0 m − 1 ( ( t + 1 ) k 2 − t k 2 ) ∑ i = 0 n i k 1 − ∑ t = 0 m − 1 ( ( t + 1 ) k 2 − t k 2 ) ∑ i = 0 ⌊ t c + c − b − 1 a ⌋ i k 1 =\sum\limits_{t=0}^{m-1}((t+1)^{k_2}-t^{k_2})\sum\limits_{i=0}^ni^{k_1}-\sum\limits_{t=0}^{m-1}((t+1)^{k_2}-t^{k_2})\sum\limits_{i=0}^{\lfloor\frac{tc+c-b-1}{a}\rfloor}i^{k_1} =t=0m1((t+1)k2tk2)i=0nik1t=0m1((t+1)k2tk2)i=0atc+cb1ik1
    ∑ i = 0 n i k 1 \sum\limits_{i=0}^ni^{k_1} i=0nik1相同, ∑ t = 0 m − 1 ( ( t + 1 ) k 2 − t k 2 ) \sum\limits_{t=0}^{m-1}((t+1)^{k_2}-t^{k_2}) t=0m1((t+1)k2tk2)同样可以插值算出,设分别为多项式 A , B A,B A,B,减号右边的式子转成:
    ∑ t = 0 m − 1 ( ∑ p = 0 k 2 A p t p ) ( ∑ q = 0 k 1 B q ( ⌊ t c + c − b − 1 a ⌋ ) q ) \sum\limits_{t=0}^{m-1}(\sum\limits_{p=0}^{k_2}A_pt^{p})(\sum\limits_{q=0}^{k_1}B_q(\lfloor\frac{tc+c-b-1}{a}\rfloor)^q) t=0m1(p=0k2Aptp)(q=0k1Bq(atc+cb1)q)
    化成 λ ∑ t = 0 m − 1 t p ( ⌊ t c + c − b − 1 a ⌋ ) q \lambda\sum_{t=0}^{m-1} t^p (\lfloor\frac{tc+c-b-1}{a}\rfloor)^q λt=0m1tp(atc+cb1)q的形式迭代求解 f ( c , c − b − 1 , a , m − 1 , p , q ) f(c,c-b-1,a,m-1,p,q) f(c,cb1,a,m1,p,q)
    因为这里 p , q p,q p,q是取遍 0 − k 1 , 0 − k 2 0-k_1,0-k_2 0k1,0k2的,所以具体求解时直接求解 g ( a , b , c , n ) g(a,b,c,n) g(a,b,c,n),返回所有合法的 f ( a , b , c , n , k 1 , k 2 ) f(a,b,c,n,k_1,k_2) f(a,b,c,n,k1,k2)的值( k 1 + k 2 ≤ 10 k_1+k_2\leq 10 k1+k210)

考虑到迭代过程中 ( a , c ) → ( a % c , c ) → ( c , a % c ) (a,c)\to (a\%c,c)\to(c,a\%c) (a,c)(a%c,c)(c,a%c),次数是 O ( l o g ( c ) ) O(log(c)) O(log(c))的,每层的枚举也最多是 O ( k 4 ) O(k^4) O(k4)的。


代码

#include
#define mem(f,x) memset(f,x,sizeof(f))
using namespace std;
typedef long long ll;
typedef unsigned int ui;

const int mod=1e9+7;
int tk,val[15],tmp[15],C[25][25];
int qa[25],qb[25];

inline void dc(int &x,int y){x-=y;if(x<0) x+=mod;}
inline int dci(int x,int y){x-=y;return x<0?x+mod:x;}
inline void ad(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline int adi(int x,int y){x+=y;return x>=mod?x-mod:x;}

inline int fp(int x,int y)
{
	int re=1;
	for(;y;y>>=1,x=(ll)x*x%mod)
	 if(y&1) re=(ll)re*x%mod;
	return re;
}

struct arr{int g[11][11];}tep;
int g[25],h[25];

struct xs{
	int sz,v[25];
	inline void mk(int *t)
	{
		ui i,j,k;mem(g,0);g[0]=1;
		for(i=0;i<21;++i){
			for(j=i+1;j;--j) 
			 g[j]=dci(g[j-1],(ll)g[j]*i%mod);
			g[0]=(mod-(ll)g[0]*i%mod)%mod;
		}
		for(i=0;i<21;++i){
			memcpy(h,g,sizeof(h));
			for(j=21;j;--j) ad(h[j-1],(ll)h[j]*i%mod);
			for(k=1,j=0;j<i;++j) k=(ll)k*(i-j)%mod;
			for(j=i+1;j<21;++j) k=(ll)k*(mod+i-j)%mod;
			k=(ll)t[i]*fp(k,mod-2)%mod;
			for(j=0;j<21;++j) ad(v[j],(ll)h[j+1]*k%mod);
		}
		for(sz=21;sz&&(!v[sz]);--sz);
	}
	inline int cal(ll x)
	{
		int re=0,bs=1,i;x%=mod;
		for(i=0;i<=sz;++i,bs=x*bs%mod) ad(re,(ll)bs*v[i]%mod);
		return re;
	}
}kda[11],kdb[11];
//a-> i^k 
//b-> (i+1)^k-i^k

arr F(int a,int b,int c,ll n)
{
    arr re;if(!n) a=0;
    int i,j,k,t,x,y,p,q,ip,iq;
	if((!a)||(n*a+b<c)){
    	for(i=0;i<=10;++i){
    		k=kda[i].cal(n);t=b/c;
    		for(j=0;i+j<=10;++j,k=(ll)k*t%mod)
    		 re.g[i][j]=k;
    	}
    	return re;
    }
    for(i=0;i<=10;++i) re.g[i][0]=kda[i].cal(n);
    if(a>=c || b>=c){
    	arr nw=F(a%c,b%c,c,n);
    	p=a/c;q=b/c;
    	for(i=0;i<=10;++i)
    	  for(j=1;i+j<=10;++j){
    	  	k=0;ip=1;
    	  	for(x=0;x<=j;++x,ip=(ll)ip*p%mod){
    	  		iq=1;
    	  		for(y=0;x+y<=j;++y,iq=(ll)iq*q%mod)
    	  		  ad(k,(ll)ip*iq%mod*(ll)C[j][x]%mod*(ll)C[j-x][y]%mod*(ll)nw.g[i+x][j-x-y]%mod);
    	  	}
    	  	re.g[i][j]=k;
    	  }
    	return re;
    }
    ll m=(n*a+b)/c;
    arr nw=F(c,c-b-1,a,m-1);
    for(i=0;i<=10;++i)
     for(j=1;i+j<=10;++j){
     	k=(ll)kdb[j].cal(m-1)*kda[i].cal(n)%mod;
     	for(x=0;x<j;++x){
     		for(y=0;y<=kda[i].sz;++y){
     		   dc(k,(ll)C[j][x]*kda[i].v[y]%mod*(ll)nw.g[x][y]%mod);	
     		}
     	}
     	re.g[i][j]=k;
     }
     return re;
}

int main(){
	int i,j,n,a,b,c,k1,k2;C[0][0]=1;
	for(i=1;i<25;++i){
		C[i][i]=C[i][0]=1;
		for(j=1;j<i;++j) C[i][j]=adi(C[i-1][j-1],C[i-1][j]);
	}
	for(i=0;i<=10;++i){
		a=b=0;
		for(j=0;j<=20;++j){
			c=fp(j,i);
			ad(a,c);ad(b,dci(fp(j+1,i),c));
			qa[j]=a;qb[j]=b;
		}
		kda[i].mk(qa);kdb[i].mk(qb);
	}
	for(scanf("%d",&tk);tk;--tk){
		scanf("%d%d%d%d%d%d",&n,&a,&b,&c,&k1,&k2);
		printf("%d\n",F(a,b,c,n).g[k1][k2]);
	}
	return 0;
}

你可能感兴趣的:(类欧几里得算法)