洛谷题单算法1-3暴力枚举

P2241 统计方形(数据加强版)

这道题目需要的数学结论如下:

    对于一个 n × m 的棋盘,我们要求其中的矩形个数(正方形+长方形)有公式如下:
        (1 + 2 + 3 + ... + n) × (1 + 2 + 3 + ... + m) = (n + 1) × n/2 × (m + 1) × m/2
    而对于一个n×n的棋盘,我们要求其中的正方形个数有如下公式:
        1×1 + 2×2 + 3×3 + ... + n×n
    那么对于n×m的棋盘,我们要求其中的正方形个数有如下公式:
        ∑ ( n − i + 1 )( m − i + 1)  其中i从 1 到 min ( n , m )

#include<iostream>
using namespace std;
#define ll long long
int main() {
	ll n, m,sum,sum1=0,sum2,p=0;
	cin >> n >> m;
	sum = (n + 1) * n * (m + 1) * m / 4;
	p = n < m ? n : m;
	for (ll i = 1; i <= p; i++) {
		sum2 = (n - i + 1) * (m - i + 1);
		sum1 += sum2;
	}
	cout << sum1 << " " << sum - sum1;
}

P2089 烤鸡

这道题目 10 层 for 循环就可以很暴力的 AC

#include<iostream>
using namespace std;
#define ll long long
int main() {
	ll n, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, cnt = 0, flag = 0;
	cin >> n;
	for (i1 = 1; i1 <= 3; i1++) {
		for (i2 = 1; i2 <= 3; i2++) {
			for (i3 = 1; i3 <= 3; i3++) {
				for ( i4 = 1; i4 <= 3; i4++) {
					for (i5 = 1; i5 <= 3; i5++) {
						for (i6 = 1; i6 <= 3; i6++) {
							for (i7 = 1; i7 <= 3; i7++) {
								for ( i8 = 1; i8 <= 3; i8++) {
									for ( i9 = 1; i9 <= 3; i9++) {
										for (i10 = 1; i10 <= 3; i10++) {
											if (i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10==n) {
												flag = 1;
												cnt++;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	if (flag == 0)
		cout << flag;
	if (flag == 1)
		cout << cnt << endl;
	for (i1 = 1; i1 <= 3; i1++) {
		for (i2 = 1; i2 <= 3; i2++) {
			for (i3 = 1; i3 <= 3; i3++) {
				for (i4 = 1; i4 <= 3; i4++) {
					for (i5 = 1; i5 <= 3; i5++) {
						for (i6 = 1; i6 <= 3; i6++) {
							for (i7 = 1; i7 <= 3; i7++) {
								for (i8 = 1; i8 <= 3; i8++) {
									for (i9 = 1; i9 <= 3; i9++) {
										for (i10 = 1; i10 <= 3; i10++) {
											if (i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 == n) {
												cout << i1 << " " << i2 << " " << i3 << " " << i4 << " " << i5 << " " << i6 << " " << i7 << " " << i8 << " " << i9 << " " << i10 << endl;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
}

P1618 三连击(升级版)

这道题目 3 层 for 循环就可以很暴力的 AC

#include<iostream>
using namespace std;
#define ll long long
//arr数组用来记录哪些数字被使用
ll arr[10] = {0,1,2,3,4,5,6,7,8,9 };
//求三位数的函数
ll num(ll i, ll j, ll k) {
	return 100 * i + 10 * j + k;
}
int main() {
	ll a, b, c, i, j, k, num1, num2, num3, i1, j1, k1, i2, j2, k2,cnt=0,s=0;
	cin >> a >> b >> c;
	if (a != 0) {
        //三层for循环枚举所有的三位数
		for (i = 1; i < 10; i++) {
			for (j = 1; j < 10; j++) {
				for (k = 1; k < 10; k++) {
                    //该三位数的三个数字肯定不能相同
					if (i != j && i != k && j != k) {
                        //求出三位数
						num1 = num(i, j, k);
                        //记录被使用的数字,赋值为0
						arr[i] = 0;
						arr[j] = 0;
						arr[k] = 0;
                        //利用比例先计算出另外两个三位数
						num2 = num1 * b / a;
						num3 = num2 * c / b;
                        //判断后,记录被使用的数字
						if (num1 < 987 && num2 < 987 && num3 < 987) {
							i1 = num2 / 100;
							k1 = num2 % 10;
							j1 = num2 % 100 / 10;
							i2 = num3 / 100;
							k2 = num3 % 10;
							j2 = num3 % 100 / 10;
							arr[i1] = 0;
							arr[j1] = 0;
							arr[k1] = 0;
							arr[i2] = 0;
							arr[j2] = 0;
							arr[k2] = 0;
                            //只有所有数字均被使用才进行输出,并且随之计数
							if (arr[0] == 0 && arr[1] == 0 && arr[2] == 0 && arr[3] == 0 && arr[4] == 0 && arr[5] == 0 && arr[6] == 0 && arr[7] == 0 && arr[8] == 0 && arr[9] == 0) {
								cout << num1 << " " << num2 << " " << num3 << endl;
								cnt++;
							}
                            //数组要开始准备重新记录
							for (s = 0; s < 10; s++) {
								arr[s] = s;
							}

						}
					}
				}
			}

		}

	}
    //不存在的特殊情况
	if (cnt == 0 || a == 0) {
		cout << "No!!!" << endl;
	}
    return 0;
}

P1036 [NOIP2002 普及组] 选数

#include<iostream>
using namespace std;
int n, k, a[25], ans;
//判断素数函数
int isprime(int x) {
	for (int i = 2; i * i < x; i++)
		if (x % i == 0)
			return 0;
	return 1;
}
//递归函数(开始位置,选择个数,选择之和)
void dfs(int start, int cnt, int sum) {
    //选择完成
	if (cnt == 0 ) {
        //所选择的和是素数则计算器加一
		if (isprime(sum) == 1)
			ans++;
		return;                //返回
	}
    //个数不足
	if (n - start + 1 < cnt)
		return;                //返回
	for (int i = start; i <= n; i++)
        //递归(位置加一,个数减一,加入所选数字)
		dfs(i + 1, cnt - 1, sum + a[i]);
}
int main() {
	cin >> n >> k;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	dfs(1, k, 0);
	cout << ans;
	return 0;
}

P1157 组合的输出

#include<iostream>
using namespace std;
int n, r;
//num数组为数字,flag数组为标记,1为选择,0为没有被选择
int num[25], flag[25];
//递归函数(开始位置,选择个数)
void dfs(int start, int cnt) {
    //选择完毕,直接输出
	if (cnt == 0) {
		for (int i = 1; i <= n; i++)
			if (flag[i] == 1)
                //注意题目要求的输出格式
				printf("%3d", num[i]);
		cout << endl;
		return ;
	}
    //个数不足直接结束
	if (n - start + 1 < cnt)
		return;
    //从开始位置遍历
	for (int i = start; i <= n; i++) {
        //选择后进行标记1
		flag[i] = 1;
        //递归
		dfs(i + 1, cnt - 1);
        //递归回来要重新标记为0
		flag[i] = 0;
	}
}
int main() {
	cin >> n >> r;
	for (int i = 1; i <= n; i++)
		num[i] = i;
	dfs(1, r);
	return 0;
}

P1706 全排列问题

#include<iostream>
using namespace std;
//num数组存数字,flag数组来记录,1为已选择,0为未选择
int n, num[10], flag[10];
//递归函数(全排列总数)
void dfs(int cnt) {
    //所有数均选好
	if (cnt == 0) {
        //注意倒着输出数组num
		for (int i = n; i > 0; i--)
			printf("%5d", num[i]);
		cout << endl;
		return;                    //返回
	}
    //遍历
	for (int i = 1; i <= n; i++) {
        //如果没有选择
		if (flag[i] == 0) {
            //把该数字存到(倒着存)数组num中
			num[cnt] = i;
			flag[i] = 1;    //标记选择
			dfs(cnt - 1);   //递归
			flag[i] = 0;    //回溯后返回原标记0
		}
	}
}
int main() {
	cin >> n;
	dfs(n);
	return 0;
}

其中 选数 组合输出 全排列 这三道题要好好区分,熟练掌握

P1088 [NOIP2004 普及组] 火星人

在这里我们可以直接使用 next_permutation(起始位置 , 结束位置) 函数,

它是C++STL提供的一个函数,用于求一个序列的下一个字典序排列,

使用时要加头文件:#include<algorithm>

#include<iostream>
#include<algorithm>
using namespace std;
int n, m, a[10005];
int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	for (int i = 1; i <= m; i++)
		next_permutation(a, a + n);
	for (int i = 0; i <= n - 2; i++)
		cout << a[i] << " ";
	cout << a[n - 1];
	return 0;
}

P3392 涂国旗

#include<iostream>
using namespace std;
int n, m;
char ch[55][55];
//定义一个稍微大一点的 ans 记录答案
long long ans = 10000;
//计数函数
long long count(int a, int b, int c) {
	long long cnt = 0;
    //白色区域
	for (int i = 1; i <= a; i++)
		for (int j = 1; j <= m; j++)
			if (ch[i][j] != 'W')
				cnt++;
    //蓝色区域
	for (int i = a + 1; i <= b; i++)
		for (int j = 1; j <= m; j++)
			if (ch[i][j] != 'B')
				cnt++;
    //红色区域
	for (int i = b + 1; i <= c; i++)
		for (int j = 1; j <= m; j++)
			if (ch[i][j] != 'R')
				cnt++;
	return cnt;
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			cin >> ch[i][j];
	int start = 1, mid = 2, end = n;
    //双重 while 循环划分所有可能存在的区域
	while (start <= n - 2) {
		while (mid <= n - 1) {
            //临时数据 temp 存储该情况的数字
			long long temp = count(start, mid, end);
            //每次计算完进行比较,更新答案
			ans = temp < ans ? temp : ans;
            //更新 mid 下标
			mid++;
		}
        //更新 start mid 下标
		start++;
		mid = start + 1;
	}
	cout << ans;
	return 0;
}

P3654 First Step (ファーストステップ)

这题注意一下K==1的时候的特殊判断即可 

#include<iostream>
using namespace std;
const int N=105;
int R,C,K,ans;
char ch[N][N];
int main(){
    cin>>R>>C>>K;
    for(int i=1;i<=R;i++) for(int j=1;j<=C;j++) cin>>ch[i][j];
    for(int i=1;i<=R;i++){
        for(int j=1;j<=C;j++){
            if(ch[i][j]=='.'){
                if(j+K-1<=C){
                    bool flag=1;
                    for(int x=j;x<=j+K-1;x++) if(ch[i][x]!='.') {flag=0;break;}
                    if(flag) ans++;
                }
                if(i+K-1<=R){
                    bool flag=1;
                    for(int x=i;x<=i+K-1;x++) if(ch[x][j]!='.') {flag=0;break;}
                    if(flag) ans++;
                }
            }
        }
    }
    if(K==1) cout<<ans/2<<endl;
    else cout<<ans<<endl;
    return 0;
}

P1217 [USACO1.5] 回文质数 Prime Palindromes

暴力超时:

#include<iostream>
#include<cmath>
using namespace std;
int a,b,ans;
//质数
bool check1(int x){
    if(x<2) return false;
    for(int i=2;i<=x/i;i++) if(x%i==0) return false;
    return true;
}
//回文
bool check2(int x){
    int num[20],flag=0;
    while(x>0){
        num[flag++]=x%10;
        x/=10;
    }
    for(int i=0;i<flag/2;i++) if(num[i]!=num[flag-i-1]) return false;
    return true;
}
int main(){
    cin>>a>>b;
    if(b>10000000) b=10000000;
    for(int i=a;i<=b;i++) if(check1(i)&&check2(i)) cout<<i<<endl;
    return 0;
}

优化 AC:

#include<iostream>
using namespace std;
const int N=1e8+5;
int a,b,ans;
//线性筛法
int primes[N],cnt; 
bool flag[N];
void get_primes(){
    for(int i=2;i<=b;i++){
        if(!flag[i]) primes[cnt++]=i;
        for(int j=0;primes[j]<=b/i;j++){
            flag[primes[j]*i]=1;
            if(i%primes[j]==0) break;
        }
    }
}
//回文
bool check(int x){
    int t=x,res=0;
    while(t!=0){
        res=res*10+t%10;
        t/=10;
    }
    return res==x;
}
int main(){
    cin>>a>>b;
    b=min(b,(int)1e8);
    get_primes();
    for(int i=0;i<=cnt;i++) if(primes[i]>=a&&check(primes[i])) cout<<primes[i]<<endl;
    return 0;
}

试除法判定质数 O(sqrt(n))

bool check_prime(int x){
    if(x<2) return 0;
    for(int i=2;i<=x/i;i++) if(x%i==0) return 0;
    return 1;
}

埃拉托斯特尼筛法 O(nloglogn)

int n,cnt,prime[N];
bool flag[N];
void get_prime(){
    for(int i=2;i<=n;i++){
        if(!flag[i]){
            prime[cnt++]=i;
            for(int j=i;j<=n;j+=i) flag[j]=1;
        }
    }
}

线性筛法 O(n)

int n,cnt,prime[N];
bool flag[N];
void get_prime(){
    for(int i=2;i<=n;i++){
        if(!flag[i]){
            prime[cnt++]=i;
            for(int j=0;prime[j]<=n/i;j++){
                flag[prime[j]*i]=1;
                if(i%prime[j]==0) break;
            }
        }
    }
}

P1149 [NOIP2008 提高组] 火柴棒等式

#include<iostream>
using namespace std;
int n,ans,a[10005],match[10]={6,2,5,5,4,5,6,3,7,6};
int fun(int z){
    if(z<=9) return match[z];
    else{
        int temp=0;
        while(z>0){
            temp+=match[z%10];
            z/=10;
        }
        return temp;
    }
}
void dfs(int x,int sum){
    if(sum>n) return ;
    if(x>3){
        if(a[1]+a[2]==a[3]&&sum==n){
            ans++;
        }
        return ;
    }
    for(int i=0;i<=1000;i++){
        a[x]=i;
        dfs(x+1,sum+fun(i));
        a[x]=0;
    }
}
int main(){
    cin>>n;n-=4;
    dfs(1,0);
    cout<<ans<<endl;
    return 0;
}

P2392 kkksc03考前临时抱佛脚

暴力搜索 AC: 

#include<iostream>
using namespace std;
const int N=25;
int n[5],a[5][25],l,r,ans,res=0x3f3f3f3f;
void dfs(int id,int x){
    if(id>n[x]){
        res=min(res,max(l,r));
        return ;
    }
    //左脑
    l+=a[x][id];
    dfs(id+1,x);
    l-=a[x][id];
    //右脑
    r+=a[x][id];
    dfs(id+1,x);
    r-=a[x][id];
}
int main(){
	for(int i=1;i<=4;i++) cin>>n[i];
	for(int i=1;i<=4;i++){
	    for(int j=1;j<=n[i];j++){
	        cin>>a[i][j];
	    }
	    dfs(1,i);
	    ans+=res;
	    l=0,r=0,res=0x3f3f3f3f;
	}
	cout<<ans<<endl;
	return 0;
}

P2036 [COCI2008-2009 #2] PERKET

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+5;
int n,a[N],b[N],c[N],i=1,j=1,k=1;
long long ans;
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) cin>>b[i];
    for(int i=1;i<=n;i++) cin>>c[i];
    sort(a+1,a+n+1);
    sort(b+1,b+n+1);
    sort(c+1,c+n+1);
    long long ta=1,tc=1,cnta=0,cntc=0;
    for(j=1;j<=n;j++){
        for(i=ta;i<=n;i++){
            if(b[j]>a[i]){
                cnta++;
            }
            else{
                break;
            }
        }
        for(k=tc;k<=n;k++){
            if(c[k]>b[j]){
                break;
            }
            else{
                cntc++;
            }
        }
        ans+=cnta*(n-cntc);
        ta=cnta+1;
        tc=cntc+1;
    }
    cout<<ans<<endl;
    return 0;
}

P3799 小Y拼木棒 

枚举木棒的长度,并且分相等和不相等分别计算即可

注意开浪浪以及枚举的顺序

#include<iostream>
#define int long long
using namespace std;
const int N=5e3+5,mod=1e9+7;
int n,ans,flag[N];
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
	    int x;
	    cin>>x;
	    flag[x]++;
	}
	for(int i=1;i<=5000;i++){
	    for(int j=i;j<=5000&&i+j<=5000;j++){
	        if(i==j){
	            int x=flag[i],y=flag[i+j];
	            if(x>=2&&y>=2) ans=(ans+y*(y-1)/2*x*(x-1)/2)%mod;
	        }
	        else{
	            int x=flag[i],y=flag[j],z=flag[i+j];
	            if(x>=1&&y>=1&&z>=2) ans=(ans+z*(z-1)/2*x*y)%mod;
	        }
	    }
	}
	cout<<ans<<endl;
	return 0;
}

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值