LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

T224535 洞天

长话短说

前面不说了,后半部分就是问你一个方案数,最少用几个平台可以造出

随便试一个

当为

到每个平台的方案数为

    1 2 3 4 5 6 7 8  9  10 11 12 13 14(n+1)
    1 1 0 1 1 1 0 0  1  1  1  1  0
    1 1 2 3 3 6 9 15 15 15 30 45 75 120

分开来看,抛去第一个,然后错一位,以每个 为分隔

    1 1 0
    1 2 3
    
    1 1 1 0  0
    3 6 9 15 15
    
    1  1  1  1  0
    15 30 45 75 120

我们发现

1.好像斐波那契数列——实际上就是

2.多个 在一起跟一个 的效果是一样的

所以我们可以用 组成斐波那契数列的第 位 (

而每一部分的最后一个又会成为下一个的第一个

所以成了若干个斐波那契数相乘的形式

显然,答案为这若干个斐波那契数的在斐波那契数列中的位置(也就是 )的和

更显然,尽量选择较大的因数是更优的

所以我们用正确的贪心,写出了错误的代码

#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=1e6+10;
int T,n,f[MAXN],fib[MAXN];
int main()
{
    scanf("%d",&T);
    fib[1]=1,fib[2]=2;
    for(int i=3;fib[i-1]<=1e6;i++) fib[i]=fib[i-1]+fib[i-2];
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n+1;i++) f[i]=0;
        f[1]=1;
        for(int i=1,a;i<=n;i++)
        {
            scanf("%d",&a);
            if(a) f[i+2]+=f[i];
            f[i+1]+=f[i];
        }
        printf("%d ",f[n+1]);
        int tmp=f[n+1],ans=0;
        for(int i=30;i>=2;i--) while(tmp%fib[i]==0) ans+=i,tmp/=fib[i];
        (f[n+1]==1)?puts("1"):printf("%d\n",ans);
    }
    return 0;
}

为什么,因为我们在分解因数的时候不能像分解质因数一样,因为有可能你分解出来了这个因数,然后就不能继续分解成斐波那契数相乘的形式了,所以我们要 一下

bool Check(int x)
{
    if(x==1) return true;
    for(int i=30;i>=2;i--) if(x%fib[i]==0&&Check(x/fib[i])) return true;
    return false;
}

跑得很快,要比题解的代码快不少

对了,还要特判 的情况

#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=1e6+10;
int T,n,f[MAXN],fib[MAXN];
bool Check(int x)
{
    if(x==1) return true;
    for(int i=30;i>=2;i--) if(x%fib[i]==0&&Check(x/fib[i])) return true;
    return false;
}
int main()
{
    scanf("%d",&T);
    fib[1]=1,fib[2]=2;
    for(int i=3;fib[i-1]<=1e6;i++) fib[i]=fib[i-1]+fib[i-2];
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n+1;i++) f[i]=0;
        f[1]=1;
        for(int i=1,a;i<=n;i++)
        {
            scanf("%d",&a);
            if(a) f[i+2]+=f[i];
            f[i+1]+=f[i];
        }
        printf("%d ",f[n+1]);
        int tmp=f[n+1],ans=0;
        for(int i=30;i>=2;i--) while(tmp%fib[i]==0&&Check(tmp/fib[i])) ans+=i,tmp/=fib[i];
        (f[n+1]==1)?puts("1"):printf("%d\n",ans);
    }
    return 0;
}
img_show