Input
第一行一个正整数,表示数据组数据 ,接下来T行
每行三个正整数N,K,P
Output
T行,每行输出一个整数,表示结果
Sample Input
1
1 2 3
Sample Output
1
Source
By Wcmg
分析:
组合数很大,考虑化掉组合数。
化简上诉式子得到
= ∑ i = 0 n [ i m o d k = = 0 ] ( n i ) ∗ F ( i ) =\sum_{i=0}^{n}[i\ mod\ k==0]\binom{n}{i}*F(i) =i=0∑n[i mod k==0](in)∗F(i)
考虑单位根反演,得到
= ∑ i = 0 n 1 k ∗ ∑ j = 0 k − 1 ( w k j ) i ∗ ( n i ) ∗ F ( i ) =\sum_{i=0}^{n}\frac{1}{k}*\sum_{j=0}^{k-1}(w_{k}^j)^i*\binom{n}{i}*F(i) =i=0∑nk1∗j=0∑k−1(wkj)i∗(in)∗F(i)
交换循环,
= 1 k ∗ ∑ j = 0 k − 1 ∑ i = 0 n ( w k j ) i ∗ ( n i ) ∗ F ( i ) =\frac{1}{k}*\sum_{j=0}^{k-1}\sum_{i=0}^{n}(w_{k}^j)^i*\binom{n}{i}*F(i) =k1∗j=0∑k−1i=0∑n(wkj)i∗(in)∗F(i)
其中, F ( i ) = A i F(i)=A^i F(i)=Ai, A A A是斐波那契数列的递推矩阵。后面就是一个二项式展开的形式。
= 1 k ∗ ∑ j = 0 k − 1 ( w k j A + I ) n =\frac{1}{k}*\sum_{j=0}^{k-1}(w_{k}^jA+I)^n =k1∗j=0∑k−1(wkjA+I)n
直接 O ( k l o g n ) O(klogn) O(klogn)算就好了。
代码:
/**************************************************************
Problem: 3328
User: liangzihao
Language: C++
Result: Accepted
Time:8932 ms
Memory:1300 kb
****************************************************************/
#include
#include
#include
#define LL long long
using namespace std;
LL G,n,w,wn,ans,mod;
int T,k,cnt;
int p[101];
struct matrix{
LL a[3][3];
}A,B;
matrix operator *(matrix a,matrix b)
{
matrix c;
for (int i=0;i<=2;i++)
{
for (int j=0;j<=2;j++) c.a[i][j]=0;
}
for (int k=1;k<=2;k++)
{
for (int i=1;i<=2;i++)
{
for (int j=1;j<=2;j++) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
}
}
return c;
}
LL ksm(LL x,LL y)
{
if (y==1) return x;
LL c=ksm(x,y/2);
c=c*c%mod;
if (y&1) c=c*x%mod;
return c;
}
void divide(int x)
{
for (int i=2;i<=trunc(sqrt(x));i++)
{
if (x%i==0)
{
p[++cnt]=i;
while (x%i==0) x/=i;
}
}
if (x>1) p[++cnt]=x;
}
void findroot(int x)
{
for (int i=2;i