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

版权声明:欢迎转载(请附带原链接)ヾ(๑╹◡╹)ノ" https://blog.csdn.net/corsica6/article/details/85097095

传送门: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}

考虑以下情况:

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

  • a c a\geq c b c b\geq c 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} ,二项式展开一下得到若干 λ 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} ,迭代求解 f ( a % c , b % c , n , k 1 , k 2 ) f(a\%c,b\%c,n,k_1,k_2) 即可。

  • 不满足上面两种情况( a < c , b < c a<c,b<c ),把 i k 2 i^{k_2} 转成 j = 0 i 1 ( j + 1 ) k 2 j k 2 \sum\limits_{j=0}^{i-1}(j+1)^{k_2}-j^{k_2} (设 0 k 2 = 0 0^{k_2}=0 )。
    m = a n + b c > 0 m=\lfloor\dfrac{an+b}{c}\rfloor>0 ,则
      f ( a , b , c , n , k 1 , k 2 ) \ \quad f(a,b,c,n,k_1,k_2)
    = 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 = 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 = 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}
    i = 0 n i k 1 \sum\limits_{i=0}^ni^{k_1} 相同, t = 0 m 1 ( ( t + 1 ) k 2 t k 2 ) \sum\limits_{t=0}^{m-1}((t+1)^{k_2}-t^{k_2}) 同样可以插值算出,设分别为多项式 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 = 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 的形式迭代求解 f ( c , c b 1 , a , m 1 , p , q ) f(c,c-b-1,a,m-1,p,q)
    因为这里 p , q p,q 是取遍 0 k 1 , 0 k 2 0-k_1,0-k_2 的,所以具体求解时直接求解 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) 的值( k 1 + k 2 10 k_1+k_2\leq 10 )

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


代码

#include<bits/stdc++.h>
#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;
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/85097095