题目描述
Farmmer John 最近收割了几乎无限多块牧草,将它们堆放在空地上。这些牧草都是正方形的,而且都有非负整数长度的边长(当然有 0)。一天它的奶牛 Bessie 发现了这些美味的牧草,于是希望把它们种在自己的秘密牧场上。他总将草皮分割成 1×1 的小块,以放入他牧场上的 N 个格子中。
Bessie 感兴趣的是,她若选取四块会有多少种不同方法。如果 N=4,那么她就有 5 种不同分法:(1,1,1,1),(2,0,0,0),(0,2,0,0),(0,0,2,0),(0,0,0,2),括号内数表示边长。注意这里不讲究顺序,如 (1,2,3,4)与 (4,3,2,1)是两种不同方法。
输入格式
仅一行,一个整数 N 。
输出格式
同样为一行,包含一个整数,为方案总数。
输入输出样例
输入 #1
4
输出 #1
5
说明/提示
对于 100% 的数据,1≤N≤10000。
分析与解:
1.暴力
#include<stdio.h>
#include<math.h>
int sqr[101];
bool app[20001];
int main() {
int n,f,ans=0;
scanf("%d",&n);
f=sqrt(n);
for(register int i=0; i<=f; i++) {
sqr[i]=i*i;
app[i*i]=true;
}
for(register int i=0; i<=f; i++) {
for(register int j=0; j<=f; j++) {
if(sqr[i]+sqr[j]>n) break;
for(register int k=0; k<=f; k++) {
if(sqr[i]+sqr[j]+sqr[k]>n) break;
if(app[n-sqr[i]-sqr[j]-sqr[k]]) {
ans++;
}
}
}
}
printf("%d",ans);
return 0;
}
2.dfs
//dfs
#include<stdio.h>
#include<math.h>
int sqr[101],n,f,ans;
int a[5];
bool app[10001];
void dfs(int p,int sum) {
if(sum>n) return;
if(p==3 && !app[n-sum]) return;
if(p==4 && n==sum) {
ans++;
return;
}
if(p>4) return;
int f2=sqrt(n-sum);
for(int i=0; i<=f2; i++) {
dfs(p+1,sum+sqr[i]);
}
}
int main() {
scanf("%d",&n);
f=sqrt(n);
for(int i=0; i<=f; i++) {
sqr[i]=i*i;
app[i*i]=true;
}
dfs(0,0);
printf("%d",ans);
return 0;
}
3.Meet in the middle
#include<stdio.h>
#include<math.h>
int sqr[101],num[10001];
bool app[20001];
int main() {
int n,f,ans=0;
scanf("%d",&n);
f=sqrt(n);
for(int i=0; i<=f; i++) {
sqr[i]=i*i;
app[i*i]=true;
}
for(int i=0; i<=f; i++) {
for(int j=0; j<=f; j++) {
if(sqr[i]+sqr[j]>n) break;
//第一步,先预处理出把一个数表示为两个完全平方数相加的方案数
num[sqr[i]+sqr[j]]++;
}
}
for(int i=0; i<=f; i++) {
for(int j=0; j<=f; j++) {
if(sqr[i]+sqr[j]>n) break;
//第二步,枚举i,j,把num[n-i^2-j^2]累加到答案中
ans+=num[n-sqr[i]-sqr[j]];
}
}
printf("%d",ans);
return 0;
}
哎,下别慌,真正的解在这里:
暴力出奇迹
#include<bits/stdc++.h>
using namespace std;
int n,ans=0;
int main()
{
cin>>n;
for(int i=0;i<=100;++i)
for(int j=0;j<=100;++j)
for(int k=0;k<=100;++k)
for(int m=0;m<=100;++m)
if(i*i+j*j+k*k+m*m==n) ans++;
cout<<ans;
return 0;
}
/*
这题可用纯暴力枚举,数据量不大(n<=10000),时间复杂度:O(100*100*100*100)。
从i=0,j=0,k=0,m=0依次枚举,当i*i+j*j+k*k+m*m==n时++ans。
最后输出。