凌乱的地下室
P2100 凌乱的地下室
思路一
注:由于本题数据过大,这里只讲解思路以及 分代码,高精度请自便。
不妨设当有 个方块时,可能的摆放数为 。
显然。
当计算 时,不妨进行模拟(用代表方块):
不妨我们再模拟一下:
由此我们可以大概猜测:数列是以为前两项的斐波那契数列。
其实到这里已经可以做题了,但作为一名优秀的数学学子,这种不完全归纳法是不一定正确的,所以我们不妨浅证明一下:
可以看到,当由 递推 时,只有最后一个数为 的情况才会产生两种情况,而其他都只会有一种。
而这个末尾为的情况是如何产生的呢?
自然是在的每一重情况后面都加上一个就得到了。
由此可得:
再用数学归纳法证明即可。
CODE(50tps)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn = 3123123;
ll ll_maxn=1e18;
inline ll read_int(){
ll a=0,f=0,g=getchar();
while(g<'0'||g>'9'){if(g=='-') f=1;g=getchar();}
while('0'<=g&&g<='9') a=a*10+g-'0',g=getchar();
return f ? -a : a;
}
inline void write(ll s,bool f){
ll top=0,a[40];
if(s<0) s=-s,putchar('-');
while(s) a[++top]=s%10,s/=10;
if(top==0) a[++top]=0;
while(top) putchar(a[top]+'0'),top--;
if(f) putchar('\n');
}
const ll mod=1e8;
const ll maxm = 5;
struct JZ{
ll jz[maxm][maxm];
ll m,n;
inline void clear(){memset(jz,0,sizeof jz),n=0,m=0;}
JZ operator * (JZ a) const{
JZ b;
b.clear();
b.m=m,b.n=a.n;
for(ll i=1;i<=b.m;i++){
for(ll e=1;e<=b.n;e++){
for(ll k=1;k<=n;k++){
b.jz[i][e]+=jz[i][k]*a.jz[k][e];
b.jz[i][e]%=mod;
}
}
}
return b;
}
inline void _write(){
for(ll i=1;i<=m;i++){
for(ll e=1;e<=n;e++){
write(jz[i][e],0),putchar(' ');
}
puts("");
}
}
inline void build(ll M,ll N){
clear();
m=M,n=N;
for(ll i=1;i<=m;i++){
for(ll e=1;e<=n;e++){
jz[i][e]=read_int();
}
}
}
inline void bz(ll N){
clear();
n=m=N;
for(ll i=1;i<=n;i++) jz[i][i]=1;
}
};
inline void read(){
JZ a1,b1;
ll n=read_int()-1;
a1.clear();
a1.m=2,a1.n=1;
a1.jz[1][1]=1,a1.jz[2][1]=2;
b1.bz(2);
JZ a2;
a2.clear();
a2.m=a2.n=2;
a2.jz[1][1]=0,a2.jz[1][2]=1,a2.jz[2][1]=1,a2.jz[2][2]=1;
while(n){
if(n&1) b1=b1*a2;
a2=a2*a2,n>>=1;
}
a1=b1*a1;
write(a1.jz[1][1],1);
}
int main (){
ll T=read_int();
while(T--) read();
}
思路二
既然知道了是斐波那契数列,为什么不直接用其通项公式计算呢?
CODE(100tps)
//题解
#include<bits/stdc++.h>
using namespace std;
map<long long ,long long>mmp; //map优化递归求斐波拉契
long long a,b,c,d;
long long dfs(long long a){
if(a==1) return 1;
if(a==2) return 1;
if(mmp[a]!=0) return mmp[a];
else return
mmp[a]=a%2==0?(dfs(a/2)+2*dfs(a/2-1))*dfs(a/2)%100000000 :
(dfs(a/2)*dfs(a/2)+dfs(a/2+1)*dfs(a/2+1))%100000000;
} //通项公式求斐波拉契
inline long long read(){
long long X=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) X=(X*10+ch-'0')%150000000,ch=getchar();
return X;
} //取摸150000000直接在快速读入中进行
int main(){
a=read();
cout<<dfs(a+1);
} //主程序真短
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】