Bessie‘s Secret Pasture S(c++)

题目描述

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。
最后输出。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值