第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代码