模拟,枚举,打表的简单应用和总结

对于一些填空题,只要一个结果,没有时间限制。所以我们将采用模拟法进行问题的求解,既然我们不需要考虑时间问题和代码问题,那么我们一定要将代码设计的具有较高的逻辑性准确性

1.需要写一些函数,将一些重复使用的功能包装起来,方便使用和找思路。

2.需要一些优化和减枝(尽量吧),例如c=a+b;如果一直a和c的范围就能找出b的范围

b的最大值就为c的最大值减a。

对于这种简单的模拟题,不需要借助算法,只要暴力的题目,我们都可以打表模拟,然后提交答案,在比赛时有的是输出答案,填空,比赛时注意分辨。

3.枚举的时候如果可以分步的话,可以先将第一步的结果先存起来,然后再往下。

常见的一些模版:

1.

求一个数有几个约数,例如 2有1和2两个约数,4有2*2和1*4一共三个约数,分别为1,2,4;

int cnt(int a){
    int ans = 0;
    for (int j = a; j > 0; j--) 
        if (a % j == 0)
            ans++;
    return ans;
}

2.求最大公约数和最小公倍数

这里再为我自己补充一下,什么是最大公约数(上学这么多年来一直不是很懂)。

最大公约数就是,好比24要除以4,24的约数分别为2*2*2*3,而4的约数为2*2,所以说最大公约数为4,换句话说就是两个数相除是要找到一个把他们不能够再化简或相除的最大的数。

int gcd(int a,int b)
{
	return a%b?gcd(b,a%b):b;
 } 

最小公倍数就是,a和b的共同拥有的倍数中最小的那个

int gad(int a,int b)
{
	if(a*b==0)
        return 0;
    return (a*b)/gcd(a,b);
}

求最小公倍数的一道例题:(注意范围) 

#include<iostream>
using namespace std;
int gcd(int a,int b)//最大公约数
{
	if(b==0)
	return a;
	else
	return gcd(b,a%b);
 } 
 int gad(int a,int b)//最小公倍数
{
	if(a*b==0)
        return 0;
    return (a*b)/gcd(a,b);
}
int main()

{
	int a,b,c;
	while(scanf("%d%d",&a,&b)!=EOF)
	{
		c=a/gcd(a,b)*b;
		printf("%d\n",c);
		//c=a*b/gcd(a,b)先做乘法会溢出 
	}
 } 

3.数组模拟法

例如在求天干地支时,天干可为 int gan[10]={"甲",“乙”,“丙”,......},所以gan[0]就表示甲

4.深刻理解continue,break,return 

int main()
{
	for()
	{
		continue;
		break;
		return ;
	}
 } 

continue表示跳过该次循环,且该次循环后面的语句也不执行了(之前一直以为还会执行continue后面的语句)

break表示跳出for循环

return表示结束主函数,直接跳到最后一个大括号那里。

return表示从被调函数中返回到主调函数中,返回的同时可以附带一个返回值,也可以不带返回值,这个返回值可以是常量、变量,也可以是表达式。作用:结束正在运行的函数,并返回函数值。

5.字符准换成数字的问题

将a转换成在字母表中的顺序

    char x;
	cin>>x;
	cout<<x-'a'+1;

'a'表示字母a所对应的ascll码值。 

6.将字符串所表示的数字转换成数字

    string a;
	cin>>a;
	int x=0;
	for(int i=0;i<a.length();i++)
	{
		x=(a[i]-'0')*pow(10,a.length()-i-1)+x;
	}
	cout<<x;

例如,输入字符123,输出的就是数字123;

关键在于,a[i]-'0',表示的是该字符所对对应的ascll码值与0所对应的差值 

7.组合型枚举的模版:

#include<iostream>
#include<vector>
using namespace std; 
int n;//共计N个数
int m;//选m个数
vector<int> chosen;
void calc(int x) {
    if (chosen.size() > m || chosen.size() + (n - x + 1) < m) //剪枝
        return;
    if (x == n + 1) { //选够了m个数输出
        for (int i = 0; i < chosen.size(); i++)
            printf("%d ", chosen[i]);
            //也可以不输出,存放起来也是可以的,主要是看题目。
        cout<<endl;
        return;
    }
    calc(x + 1);
    chosen.push_back(x);
    calc(x + 1);
    chosen.pop_back();//消除痕迹
}
int main()
{
    cin>>n>>m;
     calc(1);
}

8.排列型枚举模版

#include<iostream>
using namespace std;
int n;//共计n个数
int order[20];
bool chosen[20];
void calc(int k)
{
	if(k==n+1)
	{
		for(int i=1;i<=n;i++)
		{
			cout<<order[i]<<" ";
		}
		cout<<endl;
		return;
	}
	for(int i=1;i<=n;i++)
	{
		if(chosen[i])
		continue;
		order[k]=i;
		chosen[i]=1;
		calc(k+1);
		chosen[i]=0;
		order[k]=0;
	}
 } 
int main()
{
	cin>>n;
	calc(1);
 } 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值