勤奋的Farmer John想要建造一个四面的栅栏来关住牛们。他有一块长为n(4<=n<=2500)的木板,他想把这块本板切成4块。这四块小木板可以是任何一个长度只要Farmer John能够把它们围成一个合理的四边形。他能够切出多少种不同的合理方案。注意: *只要大木板的切割点不同就当成是不同的方案(像全排列那样),不要担心另外的特殊情况,go ahead。 *栅栏的面积要大于0. *输出保证答案在longint范围内。 *整块木板都要用完。
【原题】
勤奋的Farmer John想要建造一个四面的栅栏来关住牛们。他有一块长为n(4<=n<=2500)的木板,他想把这块本板切成4块。这四块小木板可以是任何一个长度只要Farmer John能够把它们围成一个合理的四边形。他能够切出多少种不同的合理方案。注意: *只要大木板的切割点不同就当成是不同的方案(像全排列那样),不要担心另外的特殊情况,go ahead。 *栅栏的面积要大于0. *输出保证答案在longint范围内。 *整块木板都要用完。
*第一行:一个数n
*第一行:合理的方案总数
资格赛
【分析】这道题的标算不太清楚,可能是DP吧。看到这类题目,就二话不说先打表。
我默认四边形的成立条件:三边之和大于第四边。
#include<cstdio> using namespace std; int n,i,j,k,p,ans; int main() { for (n=1;n<=50;n++) { ans=0; for (i=1;i<(n+1)/2;i++) for (j=1;j<(n+1)/2;j++) for (k=1;k<(n+1)/2;k++) if (i+j+k<n) { p=n-i-j-k; if (i+j+k<=p||i+j+p<=k||i+k+p<=j||j+k+p<=i) continue; ans++; } printf("%d ",ans); } for (;;); }
0 0 0 1 4 6 16 19 40 44 80 85 140 146 224 231 336 344 480 489
看有什么规律。我先发现隔一位的规律:0和1差1,4和6差2,16和19差3。以此类推。
现在的关键就是求另外一组相邻的关系。作差后可得:3 10 21 36 55……发现规律了吗?这有两种形式来描述:①3=1+2,10=1+2+3+4,21=1+2+3+4+5+6,……②3=1*3,10=2*5,21=3*7,36=4*9
自此,我们把规律整理一下就行了。
【AC代码】
#include<cstdio> using namespace std; int n,i,f[2505]; int main() { scanf("%d",&n); if (n<4) {puts("0");return 0;} f[4]=1; for (i=5;i<=n;i++) if (!(i&1)) f[i]=f[i-1]+i/2-1; else f[i]=f[i-1]+(i-2)*(i/2-1); printf("%d",f[n]); return 0; }