【基础算法】暴力枚举

统计方形加强版题目描述

#include
#include
using namespace std;
typedef long long ll;
int main() {
	ll n, m, squ = 0, rec = 0;
	scanf("%lld%lld", &n, &m);
	for(ll x = 0; x <= n; x++)  
		for(ll y = 0; y <= m; y++) { 
			ll tmp = min(x, y);  //统计左上角斜线的格点
			squ += tmp;
			rec += x * y - tmp; 
		}
	printf("%lld %lld", squ, rec);
    return 0;
}

三连击升级版 题目描述

//方法1
//通过枚举一个3位来确定另外两个3位 
#include
#include
#include
#include 
using namespace std;
int b[10];
void go(int x) {
	b[x % 10] = 1;
	b[x / 10 % 10] = 1;
	b[x / 100] = 1; 
}
bool check(int x, int y, int z) {
	memset(b, 0, sizeof(b));
	if(y > 999 || z > 999) return 0;
	go(x), go(y), go(z);
	for(int i = 1; i <= 9; i++) 
	    if(!b[i]) return 0;
	return 1;
}
int main() {
	long long a, b, c, x, y, z, cnt = 0;
	cin >> a >> b >> c;
	for(x = 123; x <= 987; x++) {
		if(x * b % a && x * c % a) continue;
		y = x * b / a, z = x * c / a;
		if(check(x, y, z)) 
		    printf("%lld %lld %lld\n", x, y, z), cnt++; 
	} 
	if(!cnt)  cout << "No!!!" << endl;
    return 0;
}

//方法2
//使用next_permutation(start, end)产生下一个字典序排列 
#include
#include
#include
using namespace std;
typedef long long ll;
int w[10];
int main() {
	ll a, b, c, x, y, z, cnt = 0;
	cin >> a >> b >> c;
	for(int i = 1; i <= 9; i++) w[i] = i; 
	do {
		x = w[1] * 100 + w[2] * 10 + w[3];
		y = w[4] * 100 + w[5] * 10 + w[6];
		z = w[7] * 100 + w[8] * 10 + w[9];
		if(x * b == y * a && y * c == z * b) 
			printf("%lld %lld %lld\n", x, y, z), cnt++;
	} while(next_permutation(w+1, w+10));
	if(!cnt)  cout << "No!!!" << endl;
    return 0;
}

 选数题目描述

//方法1
#include
#include
using namespace std;
int a[30];
bool check(int x) {  //判断质数 
	for(int i = 2; i * i <= x; i++)
	    if(x % i == 0) return 0;
	return 1; 
}
int main() {
	int n, k, ans = 0;
	cin >> n >> k;
	for(int i = 0; i < n; i++) scanf("%d", &a[i]);
	int u = 1 << n;  //全集 
	for(int s = 0; s < u; s++)  //枚举所有子集[0, u) 
    /*
    1 __builtin_popcount()返回一个数二进制下1的个数
    2 a<>n等于a整除2的n次方
    */
		if(__builtin_popcount(s) == k) {  //找到k元子集 
			int sum = 0;
			for(int i = 0; i < n; i++)
			    if(s & (1 << i)) sum += a[i];  //如果第i个元素在s中 
			if(check(sum)) ans++;
		}
	cout << ans;
    return 0;
}

//方法2
#include
#include
using namespace std;
int x[20], n, k; 
bool isprime(int n){ //判断是否质数
    int s = sqrt(double(n));
    for(int i = 2; i <= s; i++)
        if(n % i == 0) return false;
    return true;
}
int rule(int left_num, int a_sum, int start, int end){
    /*
	left_num为剩余的k,alr_sum为前面累加的和 
    start和end为全组合剩下数字的选取范围;调用递归生成全组合,在过程中逐渐把K个数相加
    当选取的数个数为0时,直接返回前面的累加和是否为质数即可 
	*/ 
    if(left_num == 0)  return isprime(a_sum);
    int sum = 0;
    for(int i = start; i <= end; i++) 
        sum += rule(left_num - 1, a_sum + x[i], i + 1, end);
    return sum;
}
int main(){
    cin >> n >> k;
    for(int i = 0; i < n; i++)  cin >> x[i];
    cout << rule(k, 0, 0, n - 1); //调用递归解决问题
}

组合的输出题目描述

//从高位到低位表示,可以让1尽量出现在靠前位置
#include
#include
using namespace std;
int a[30];
int main() {
	int n, r;
	cin >> n >> r;
	for(int s = (1 << n) - 1; s >= 0; s--) {
		int cnt = 0;
		for(int i = 0; i < n; i++) 
		    if(s & (1 << i)) a[cnt++] = i;
		if(cnt == r) {
			for(int i = r - 1; i >= 0; i--) 
				printf("%3d", n - a[i]); 
			cout << endl;
		} 
	}
    return 0;
}

火柴棒等式题目描述

#include
using namespace std;
int c[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6}; 

int main() {
	int a[2001] = {6}, b, s = 0, i, j;	
    scanf("%d", &b);
    for(i = 1; i <= 2000; i++) {
        j = i;
        while(j > 0) { //求每个数所用的火柴棒
            a[i] += c[j%10];
            j /= 10;
        }
    }
    for(i = 0; i <= 1000; i++) {
        for(j = 0; j <= 1000; j++)
        if(a[i] + a[j] + a[i+j] + 4 == b) s++; //还有加号与等号
    }
    printf("%d", s); 
    return 0;
}

 妖梦拼木棒题目描述

#include
#include
using namespace std;
const int kMaxn = 1e5 + 10;
const int kMod = 1e9 + 7;
long long count = 0;

long long f(int q) {  //求组合数,在q里面选2个
	return (q - 1) * q / 2;
} 

int main() {
	int maxlen = 2, n, a[kMaxn], x;
	cin >> n;
	for(int i = 0; i < n; i++) {
		cin >> x;
		a[x]++;
		if(x > maxlen) maxlen = x;
	}
	for(int i = 2; i <= maxlen; i++) 
		if(a[i] >= 2) 
			for(int j = 1; j < i / 2 + 1; j++) 
			    if((i - j) != j) 
			    	count += a[j] * a[i - j] * f(a[i]);
				else if ((i - j) == j && a[j] >= 2) 
				    count += f(a[i]) * f(a[j]);
	cout << count % kMod << endl;
    return 0;
}

 回文质数题目描述

#include
#include
#define MAXN 10000005  //偶数位数回文数(除11)必定不是质数,所以只要运行到10000000。
using namespace std;
int prime[MAXN];

bool pd_h(int x) {
    int y = x, num = 0;  //int y=x,防止x被改变
    while (y != 0) {
        num = num * 10 + y % 10;  //上一次数字的记录进位再加上下一位数
        y /= 10;
    } 
    if (num == x) return 1;
    else return 0;
}

int main() {
    int a, b;
    cin >> a >> b;
    int cnt = 0;
    if(b > 10000000) b = 10000000;
    for (int i = 0; i < MAXN; i++) prime[i] = 1;  //先把每个数都定义为合数
    for (int i = 2; i < MAXN; i++) {  
        if (!prime[i]) continue;  
        for (int j = i * 2; j < MAXN; j+=i) prime[j] = 0;  //将i的倍数标记为合数
    }  
    for(int i = a; i <= b; i++) {
        if(i > 10000000) break;
        if(pd_h(i) && prime[i]) printf("%d\n", i);
    }
}

报数题目描述 

#include
using namespace std;
const int INF = 1e7 + 10;
int vis[INF], vk[INF];
mapkv; 

int main() {
	int t, x, k = 1;
	for(int i = 1; i < INF; i++) {
		int c = i;
		if(!vis[i]) 
			while(c) {
				if(c % 10 == 7) {
					for(int j = 1; j * i < INF; j++) vis[i * j] = true; 
					break;
				}
				c /= 10; 
			} 
		if(!vis[i]) {
			kv[i] = k, vk[k] = i, k++;
		}
	}
	cin >> t;
	while(t--) {
		cin >> x;
		if(vis[x]) cout << -1 << endl;
		else cout << vk[kv[x] + 1] << endl;
	} 
	return 0;
}

你可能感兴趣的:(程序设计竞赛基础,c++,算法)