题意
求
∑
i
=
0
n
∑
j
=
0
⌊
i
2
⌋
C
i
−
1
j
\sum_{i=0}^n\sum_{j=0}^{\lfloor\frac{i}{2}\rfloor}C_{i-1}^j
∑i=0n∑j=0⌊2i⌋Ci−1j
n
≤
1
0
10000
n≤10^{10000}
n≤1010000
题解
对组合数的感知。
题目给组合数,希望我们能够正确理解其意义。
假设i固定了,那么
∑
j
=
0
⌊
i
2
⌋
C
i
−
1
j
\sum_{j=0}^{\lfloor\frac{i}{2}\rfloor}C_{i-1}^j
∑j=0⌊2i⌋Ci−1j就代表一堆石子有i个,一次可以拿1个或2个。问将石子拿完的方案数。
显然是斐波那契数列。
最直接的想法:n很大,那么压位。斐波那契?矩乘。
下面是我的AC代码。
有一位大佬提出,n虽然很大,但是答案一定有循环节,且循环节不超过998244353+1。(显然)
所以,n只需要模998244354即可。
然后闪过。。。
Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define N 2005
#define mo 998244353
#define Mo 100000000
#define LL long long
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
struct eq{
int a[N];
int l;
void clear(){
memset(a,0,sizeof(a));
}
}f1;
struct mat{
int i,j,a[2][2];
void clear(){
memset(a,0,sizeof(a));
}
void unit(){
clear();
fo(i,0,1)a[i][i]=1;
}
}F1,F2,F3;
char s[10010];
int len,Len,i,j,k,n,m,ans;
int cnt,x2;
int Max(int x,int y){return x>y?x:y; }
eq plus(eq a,eq b){
eq c;c.clear();
int i,l=Max(a.l,b.l);
fo(i,1,l){
c.a[i]=a.a[i]+b.a[i];
c.a[i+1]=c.a[i]/Mo;
c.a[i]=c.a[i]%Mo;
}
c.l=l+1;
while(!c.a[c.l]&&c.l>1)c.l--;
return c;
}
eq divd(eq a,int b){
eq c;c.clear();
int i,l=a.l;
LL ys=0;
fd(i,l,1){
ys=(1ll*ys*Mo+1ll*a.a[i]);
c.a[i]=c.a[i]+(ys/b);
ys=(ys-1ll*c.a[i]*b);
}
c.l=l;
while(!c.a[c.l]&&c.l>1)c.l--;
return c;
}
mat M_mul(mat a,mat b){
mat c;c.clear();
int i,j,k;
fo(k,0,1)fo(i,0,1)if(a.a[i][k]){
fo(j,0,1)c.a[i][j]=(1ll*c.a[i][j]+(1ll*a.a[i][k]*b.a[k][j])%mo)%mo;
}
return c;
}
int main(){
scanf("%s\n",s+1);
len=strlen(s+1);
if(len==1&&s[1]=='0'){
printf("1");
return 0;
}
cnt=0;x2=0;
for(i=len;i>0;i-=8){
if(i<=8){
x2=0;
fo(j,1,i)x2=(x2<<3)+(x2<<1)+(s[j]^'0');
f1.a[++Len]=x2;
break;
}
x2=0;
fo(j,i-7,i)x2=(x2<<3)+(x2<<1)+(s[j]^'0');
f1.a[++Len]=x2;
}
f1.l=Len;
F2.unit();
F3.a[0][1]=F3.a[1][0]=F3.a[1][1]=1;
while(!(f1.l==1&&f1.a[1]==0)){
if(f1.a[1]&1)F2=M_mul(F2,F3);
f1=divd(f1,2);
F3=M_mul(F3,F3);
}
ans=(1ll*F2.a[0][0]+F2.a[0][1])%mo;
ans=(1ll*ans*(1ll*F2.a[1][0]+F2.a[1][1]))%mo;
printf("%d",ans);
return 0;
}