loj138-solution

LOJ#138 Solution

link

给你 \(n,a,b,c,k_1,k_2\),求 \(\displaystyle\sum_{x=0}^nx^{k_1}\lfloor\frac{ax+b}c\rfloor^{k_2}\)

\(T=1000,1\le n,a,b,c\le 10^9,0\le k_1+k_2\le10\)

\(\displaystyle f(n,a,b,c,k_1,k_2)=\sum_{x=0}^nx^{k_1}\lfloor\frac{ax+b}c\rfloor^{k_2}\)

  • \(a=0\)

\(\displaystyle f(n,a,b,c,k_1,k_2)=\lfloor\frac{b}c\rfloor^{k_2}\sum_{x=0}^nx^{k_1}\),这里右边的部分是经典的自然数幂和,插值解决即可。

  • \(a\ge c\)

\(a=qc+r(0\le r<c)\),则

\(\begin{aligned} f(n,a,b,c,k_1,k_2) &=\sum_{x=0}^nx^{k_1}(qx+\lfloor\frac{rx+b}c\rfloor)^{k_2}\\ &=\sum_{x=0}^nx^{k_1}\sum_{i=0}^{k_2}(qx)^i\lfloor\frac{rx+b}c\rfloor^{k_2-i}\binom{k_2}i\\ &=\sum_{i=0}^{k_2}q^i\binom{k_2}i\sum_{x=0}^nx^{k_1+i}\lfloor\frac{rx+b}c\rfloor^{k_2-i}\\ &=\sum_{i=0}^{k_2}q^i\binom{k_2}if(n,r,b,c,k_1+i,k_2-i) \end{aligned}\)

递归计算即可。

  • \(b\ge c\)

\(b=qc+r(0\le r<c)\),则

\(\begin{aligned} f(n,a,b,c,k_1,k_2) &=\sum_{x=0}^nx^{k_1}(q+\lfloor\frac{ax+r}c\rfloor)^{k_2}\\ &=\sum_{x=0}^nx^{k_1}\sum_{i=0}^{k_2}q^i\lfloor\frac{ax+r}c\rfloor^{k_2-i}\binom{k_2}i\\ &=\sum_{i=0}^{k_2}q^i\binom{k_2}i\sum_{x=0}^nx^{k_1}\lfloor\frac{ax+r}c\rfloor^{k_2-i}\\ &=\sum_{i=0}^{k_2}q^i\binom{k_2}if(n,a,r,c,k_1,k_2-i) \end{aligned}\)

递归计算即可。

  • \(a<c,b<c\)

\(\displaystyle m=\lfloor\frac{an+b}c\rfloor\),则

\(\begin{aligned} f(n,a,b,c,k_1,k_2) &=\sum_{x=0}^nx^{k_1}\sum_{i=0}^{\lfloor\frac{ax+b}c\rfloor-1}((i+1)^{k_2}-i^{k_2})\\ &=\sum_{i=0}^{m-1}((i+1)^{k_2}-i^{k_2})\sum_{x=0}^nx^{k_1}[\lfloor\frac{ax+b}c\rfloor-1\ge i]\\ &=\sum_{i=0}^{m-1}((i+1)^{k_2}-i^{k_2})\sum_{x=0}^nx^{k_1}[x>\lfloor\frac{ci+c-b-1}a\rfloor]\\ &=\sum_{i=0}^{m-1}((i+1)^{k_2}-i^{k_2})\sum_{x=0}^nx^{k_1}-\sum_{i=0}^{m-1}((i+1)^{k_2}-i^{k_2})\sum_{x=0}^{\lfloor\frac{ci+c-b-1}a\rfloor}x^{k_1}\\ &=m^{k_2}\sum_{x=0}^nx^{k_1}-\sum_{i=0}^{m-1}((i+1)^{k_2}-i^{k_2})\sum_{x=0}^{\lfloor\frac{ci+c-b-1}a\rfloor}x^{k_1}\\ \end{aligned}\)

前半部分可以直接计算,考虑后半部分。

我们知道 \((i+1)^{k_2}-i^{k_2}\) 是关于 \(i\)\(k_2-1\) 次多项式,系数可以二项式定理直接计算;\(\sum_{x=0}^{\lfloor\frac{ci+c-b-1}a\rfloor}x^{k_1}\) 是关于 \(\lfloor\frac{ci+c-b-1}a\rfloor\)\(k_1+1\) 次多项式,系数可以插值求出。我们设这两个多项式分别为 \(G,H\),则

\(\begin{aligned} \sum_{i=0}^{m-1}((i+1)^{k_2}-i^{k_2})\sum_{x=0}^{\lfloor\frac{ci+c-b-1}a\rfloor}x^{k_1} &=\sum_{i=0}^{m-1}\sum_{j=0}^{k_2-1}g_ji^j\sum_{k=0}^{k_1+1}h_k\lfloor\frac{ci+c-b-1}a\rfloor^k\\ &=\sum_{j=0}^{k_2-1}g_j\sum_{k=0}^{k_1+1}h_k\sum_{i=0}^{m-1}i^j\lfloor\frac{ci+c-b-1}a\rfloor^k\\ &=\sum_{j=0}^{k_2-1}g_j\sum_{k=0}^{k_1+1}h_kf(m-1,c,c-b-1,a,j,k)\\ \end{aligned}\)

递归计算即可。

代码

using namespace std;
const int N = 2 + 10;
const int inf = ~0u >> 2;
const int p = 1e9 + 7;
int C[N][N],sum[N][N];
int qpow(int a , int k)
{
	int res = 1;
	while(k)
	{
		if(k & 1)
			res = 1ll * res * a % p;
		a = 1ll * a * a % p;
		k >>= 1;
	}
	return res;
}
struct matrix
{
	int data[N][N];
	int* operator [] (int x)
		{return data[x];}
	matrix()
		{memset( data , 0 , sizeof(data) );}
};
matrix solve(int n , int a , int b , int c)
{
	matrix res;
	if(!a)
	{
		for(int k1 = 0;k1 <= 10;k1++)
		{
			int ps = 0;
			for(int i = 0,nk = 1;i <= k1 + 1;i++,nk = 1ll * nk * n % p)	
				ps = (ps + 1ll * sum[k1][i] * nk % p) % p;
			for(int k2 = 0,prd = 1;k1 + k2 <= 10;k2++,prd = 1ll * prd * (b / c) % p)
				res[k1][k2] = 1ll * prd * ps % p;
		}
		return res;
	}
	if(a >= c)
	{
		matrix t = solve(n , a % c , b , c);
		for(int k1 = 0;k1 <= 10;k1++)
			for(int k2 = 0;k1 + k2 <= 10;k2++)
				for(int i = 0,qk = 1;i <= k2;i++,qk = 1ll * qk * (a / c) % p)
					res[k1][k2] = (res[k1][k2] + 1ll * qk * C[k2][i] % p * t[k1 + i][k2 - i] % p) % p;
		return res;
	}
	if(b >= c)
	{
		matrix t = solve(n , a , b % c , c);
		for(int k1 = 0;k1 <= 10;k1++)
			for(int k2 = 0;k1 + k2 <= 10;k2++)
				for(int i = 0,qk = 1;i <= k2;i++,qk = 1ll * qk * (b / c) % p)
					res[k1][k2] = (res[k1][k2] + 1ll * qk * C[k2][i] % p * t[k1][k2 - i] % p) % p;
		return res;
	}
	int m = (1ll * a * n + b) / c;
	matrix t = solve(m - 1 , c , c - b - 1 , a);
	for(int k1 = 0;k1 <= 10;k1++)
	{
		int ps = 0;
		for(int i = 0,nk = 1;i <= k1 + 1;i++,nk = 1ll * nk * n % p)
			ps = (ps + 1ll * sum[k1][i] * nk % p) % p;
		for(int k2 = 0,mk = 1;k1 + k2 <= 10;k2++,mk = 1ll * mk * m % p)
		{
			res[k1][k2] = 1ll * mk * ps % p;
			for(int j = 0;j <= k2 - 1;j++)
				for(int k = 0;k <= k1 + 1;k++)
					res[k1][k2] = (res[k1][k2] - 1ll * C[k2][j] * sum[k1][k] % p * t[j][k] % p + p) % p;
		}
	}
	return res;
}
void lagrange(int n , int *y , int *res)
{
	static int a[N],b[N];
	memset( a , 0 , sizeof(a) );
	a[0] = 1;
	for(int i = 1;i <= n;i++)
		for(int j = i - 1;~j;j--)
		{
			a[j + 1] = ( a[j + 1] + a[j] ) % p;
			a[j] = (p - 1ll * a[j] * i % p) % p;
		}
	for(int i = 1;i <= n;i++)
	{
		memset( b , 0 , sizeof(b) );
		for(int j = n - 1;~j;j--)
			b[j] = (a[j + 1] + 1ll * b[j + 1] * i % p) % p;
		int c = 1;
		for(int j = 1;j <= n;j++)
			if(i != j)
				c = 1ll * c * (i - j + p) % p;
		c = qpow(c , p - 2);
		for(int j = 0;j <= n;j++)
			res[j] = (res[j] + 1ll * b[j] * c % p * y[i] % p) % p;
	}
}
int y[N];
int main()
{
	for(int i = 0;i <= 10;i++)
	{
		y[0] = !i;
		for(int j = 1;j <= i + 2;j++)
			y[j] = ( y[j - 1] + qpow(j , i) ) % p;
		lagrange( i + 2 , y , sum[i] );
	}
	C[0][0] = 1;
	for(int i = 1;i <= 10;i++)
	{
		C[i][0] = 1;
		for(int j = 1;j <= i;j++)
			C[i][j] = ( C[i - 1][j - 1] + C[i - 1][j] ) % p;
	}
	int t;
	cin >> t;
	while(t--)
	{
		int n,a,b,c,k1,k2;
		scanf("%d%d%d%d%d%d" , &n , &a , &b , &c , &k1 , &k2);
		printf( "%d\n" , solve(n , a , b , c)[k1][k2] );
	}
    return 0;
}
posted @ 2024-02-29 07:55  iorit  阅读(15)  评论(0)    收藏  举报