【SNOI2017 DAY1】礼物
数据范围非常之大 完全没有其它想法 一定是和二分有关(当然你也可以背公式)
假设前面的人一共送了 S S ,那么当前这个人送的就是 S+i∗i S + i ∗ i
当前的和就是 S∗2+i∗i S ∗ 2 + i ∗ i
因此我们给定一个一维矩阵
为什么这样子定矩阵呢??
因为
然后单独取出 S S 的系数
对于 ik i k 为 1 1
对于 S S 为 2 2
最后把 S、ik S 、 i k 相加即为结果
#include
#include
#include
using namespace std;
const long long mod=1e9+7;
int S;
struct mat
{
long long x[123][123];
mat(){memset(x,0,sizeof(x));}
mat operator*(mat &B)const
{
mat C;
for(int a=0;afor(int b=0;bfor(int mid=0;midreturn C;
}
};
long long C[123][123];
void GetC(int n)
{
C[0][0]=C[1][0]=C[1][1]=1;
for(int i=1;i<=n;i++)
{
C[i][0]=1;
for(int j=1;j<=n;j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
mat KSM(mat A,mat B,long long T)
{
while(T)
{
if(T&1)A=A*B;
T>>=1;
B=B*B;
}
return A;
}
long long N;int K;
mat A,B;
int main()
{
//freopen("In.txt","r",stdin);
scanf("%lld%d",&N,&K);
GetC(K);
for(int i=0;i<=K;i++)
for(int j=0;j<=i;j++)
B.x[j][i]=C[i][j];
S=K+3;
B.x[K][K+1]=B.x[K+2][K+1]=1;
B.x[K][K+2]=1;B.x[K+2][K+2]=2;
//A.x[0][0]=A.x[0][K+1]=1;
for(int i=0;i<=K+1;i++)A.x[0][i]=1;
A=KSM(A,B,N);
printf("%lld",A.x[0][K+1]);
}