loj138-solution
LOJ#138 Solution
给你 \(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;
}

浙公网安备 33010602011771号