第2题:母牛生小牛

第2题:母牛生小牛

这一题呢,我用了许多种尝试,刚开始用了递归暴力模拟,我想大家都能看懂。

#include <bits/stdc++.h>
using namespace std;
unsigned long long n;
unsigned long long ss(unsigned long long x){
    unsigned long long y=x+3;
    unsigned long long ans=1;
    if(y<=n)ans+=ss(y);
    for(unsigned long long i=y+2;i<=n;i+=2)ans+=ss(i);
    return ans;
}
int main(){
    cin>>n;
    cout<<ss(0);
    return 0;
}

40分

后面几个点都TLE了

只有unsigned long long呢,它可以将long long负数存储的那些空间全部挪到存正数的空间里来。

我加了个记忆化,然后提交

#include <bits/stdc++.h>
using namespace std;
unsigned long long n,sum[1010];
unsigned long long ss(unsigned long long x){
    if(sum[x]!=0)return sum[x];
    unsigned long long y=x+3;
    unsigned long long ans=1;
    if(y<=n)ans+=ss(y);
    for(unsigned long long i=y+2;i<=n;i+=2)ans+=ss(i);
    sum[x]=ans;
    return ans;
}
int main(){
    cin>>n;
    cout<<ss(0);
    return 0;
}

60分

后面几个点都WA了

这很明显,能推出状态转移方程,于是,我推了,还加了个高精。

我的状态表示是f[i]表示在第i年出生的小牛,到第n年,总共会创造有多少头奶牛,包括他本生。

#include <bits/stdc++.h>
using namespace std;
string dp[1010];
int x[510],y[510];
string jf(string a,string b){
    memset(x,0,sizeof(x));
    memset(y,0,sizeof(y));
    if(a.size()<b.size())swap(a,b);
    int c=-1,l1,l2,d=-1;
    for(int i=a.size()-1;i>=0;i--){
        c++;
        x[c]=a[i]-48; 
    }l1=a.size();
    for(int i=b.size()-1;i>=0;i--){
        d++;
        y[d]=b[i]-48; 
    }l2=b.size();
    for(int i=0;i<l1;i++){
        y[i]+=x[i];
        y[i+1]+=y[i]/10;
        y[i]%=10;
    }
    string s="";
    if(y[l1]!=0)s+=to_string(y[l1]);
    for(int i=l1-1;i>=0;i--)s+=to_string(y[i]);
    return s;
}
int main(){
    int n;
    cin>>n;
    for(int i=n;i>=0;i--){
        int y=i+3;
        dp[i]='1';
        for(int j=y;j<=n;j+=2)dp[i]=jf(dp[i],dp[j]);
    }cout<<dp[0];
    return 0;
}

代码出来了,80分,最后2个点TLE了

很显然,状态状态转移方程太复杂。

我们来列个表看看。

1 2 3 4 5 6 7 8 9
1 1 2 2 3 4 5 7 9

咦,好像有什么规律呢!

从第4项开始,每项都是前2项和前3项的和,哇!

#include <bits/stdc++.h>
using namespace std;
string dp[1010];
int x[510],y[510];
string jf(string a,string b){
    memset(x,0,sizeof(x));
    memset(y,0,sizeof(y));
    if(a.size()<b.size())swap(a,b);
    int c=-1,l1,l2,d=-1;
    for(int i=a.size()-1;i>=0;i--){
        c++;
        x[c]=a[i]-48; 
    }l1=a.size();
    for(int i=b.size()-1;i>=0;i--){
        d++;
        y[d]=b[i]-48; 
    }l2=b.size();
    for(int i=0;i<l1;i++){
        y[i]+=x[i];
        y[i+1]+=y[i]/10;
        y[i]%=10;
    }
    string s="";
    if(y[l1]!=0)s+=to_string(y[l1]);
    for(int i=l1-1;i>=0;i--)s+=to_string(y[i]);
    return s;
}
int main(){
    int n;
    cin>>n;
    dp[1]='1';
    dp[2]='1';
    dp[3]='2';
    for(int i=4;i<=n;i++)dp[i]=jf(dp[i-2],dp[i-3]);
	cout<<dp[n];
    return 0;
}

这就是AC代码

原文地址:https://www.cnblogs.com/zhaohaikun/p/12816996.html