信息竞赛--打表法讲解

对于数据小又容易超时的题,可以采取打表法

打表就是将所有输入情况的答案保存在代码中,输入数据后直接输出就可以了

打表法具有快速,易行(可以写暴力枚举程序)的特点,缺点是代码可能太大,或者情况覆盖不完

对于不会超时,数据规模适合打表,为了简洁你也可以打表

例一:NOIP2008T2

这道题n<=20完全可以打表,代码(生成答案):

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main(){
	freopen("ans.txt","w",stdout);
	int a[10]={6,2,5,5,4,5,6,3,7,6};
	int i,j,temp=0,num=0,k,in[2020],n;
	in[0]=6;
	for(i=1;i<=2000;i++){
		k=i;
		temp=0;
		while(k){
			temp+=a[k%10];
			k/=10;
		}
		in[i]=temp;
	}
	n=0;
	Again:
	num=0;
	for(i=0;i<=999;i++){
		for(j=0;j<=999;j++){
			if(n==in[i]+in[j]+in[i+j]+4) num++;
		}
	}
	printf("%d,",num);
	if(n<24){n++;goto Again;}
	return 0;
}

提交代码:

#include<iostream>
using namespace std;
int ans[]={0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,8,9,6,9,29,39,38,65,88,128};
int n;
int main(){
	cin>>n;
	cout<<ans[n]<<'\n';
	return 0;
}

是不是很简洁

例二:骨牌问题[3]

Description

  在《骨牌问题[版本1]》中问题描述为:“有 2 行 n 列的长方形,用 n 个 1*2 的骨牌铺满,请计算有多少种铺法。”我们知道这个问题可用递推算法来解决,递推方程如下:
   d[1]=1;
   d[2]=2;
   d[n]=d[n-1]+d[n-2] (n>2)
  现在我们把这个问题推广一下:“有 m 行 n 列的长方形,用 (m*n)/2 个 1*2 的骨牌铺满,请计算有多少种铺法。

Input

若干行,每行包含两个整数:m,n,表示长方形的行和列的数量。

Output

若干行,每行一个整数,对应输入中的长方形铺满的方案数。

Sample Input 1 

1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11

Sample Output 1

1
0
1
2
3
5
144
51205

Hint

m*n<=121

由于目前主要目的是讲打表法,此题解法不重点说明,反正正解是用的状压DP

这道题m*n<=121完全可以用打表的方法,先状压DP生成表:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m,ALL;
ll d[121][2058];
int A,B;
void shift(int i,int j,int A_){
	if(j>n-1){
		d[i][B]=d[i][B]+d[i-1][A_];
		return;
	}
	if(A_&(1<<j)){
		B=B&(~(1<<j)); shift(i,j+1,A_);
	}
	if(j<n-1&&(A_&(1<<j))&&(A_&(1<<(j+1)))){
		B|=(1<<j);B|=(1<<(j+1));shift(i,j+2,A_);
	}
	if(!(A&(1<<j))){
		B|=(1<<j);shift(i,j+1,A_);
	}
}
void dp(){
	if(n>m) swap(n,m);
	ALL=(1<<n)-1;
	memset(d,0,sizeof(d));
	d[0][ALL]=1;
	for(int i=0;i<m;i++)
	for(A=0;A<=ALL;A++){
		B=0;
		shift(i+1,0,A);
	}
}
int main(){
	freopen("ans.txt","w",stdout);//输出到答案表中 
	int cnt=0;
	printf("\t");
	for(int i=1;i<=121;i++)
	for(int j=1;i*j<=121;j++) if(i*j%2==0&&i<=j){//枚举情况 
		n=i;m=j;
		dp();//状压DP 
		cnt++;
		printf("f[%d][%d]=%lldLL",i,j,d[m][ALL]);
		printf("%s",cnt%3?",":";\n\t");//格式控制 
	}
	return 0;
}

然后把答案copy到程序中就可以了:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll f[20][150];
int x,y;
void get_V(){
	f[1][2]=1LL,f[1][4]=1LL,f[1][6]=1LL;
	f[1][8]=1LL,f[1][10]=1LL,f[1][12]=1LL;
	f[1][14]=1LL,f[1][16]=1LL,f[1][18]=1LL;
	f[1][20]=1LL,f[1][22]=1LL,f[1][24]=1LL;
	f[1][26]=1LL,f[1][28]=1LL,f[1][30]=1LL;
	f[1][32]=1LL,f[1][34]=1LL,f[1][36]=1LL;
	f[1][38]=1LL,f[1][40]=1LL,f[1][42]=1LL;
	f[1][44]=1LL,f[1][46]=1LL,f[1][48]=1LL;
	f[1][50]=1LL,f[1][52]=1LL,f[1][54]=1LL;
	f[1][56]=1LL,f[1][58]=1LL,f[1][60]=1LL;
	f[1][62]=1LL,f[1][64]=1LL,f[1][66]=1LL;
	f[1][68]=1LL,f[1][70]=1LL,f[1][72]=1LL;
	f[1][74]=1LL,f[1][76]=1LL,f[1][78]=1LL;
	f[1][80]=1LL,f[1][82]=1LL,f[1][84]=1LL;
	f[1][86]=1LL,f[1][88]=1LL,f[1][90]=1LL;
	f[1][92]=1LL,f[1][94]=1LL,f[1][96]=1LL;
	f[1][98]=1LL,f[1][100]=1LL,f[1][102]=1LL;
	f[1][104]=1LL,f[1][106]=1LL,f[1][108]=1LL;
	f[1][110]=1LL,f[1][112]=1LL,f[1][114]=1LL;
	f[1][116]=1LL,f[1][118]=1LL,f[1][120]=1LL;
	f[2][2]=2LL,f[2][3]=3LL,f[2][4]=5LL;
	f[2][5]=8LL,f[2][6]=13LL,f[2][7]=21LL;
	f[2][8]=34LL,f[2][9]=55LL,f[2][10]=89LL;
	f[2][11]=144LL,f[2][12]=233LL,f[2][13]=377LL;
	f[2][14]=610LL,f[2][15]=987LL,f[2][16]=1597LL;
	f[2][17]=2584LL,f[2][18]=4181LL,f[2][19]=6765LL;
	f[2][20]=10946LL,f[2][21]=17711LL,f[2][22]=28657LL;
	f[2][23]=46368LL,f[2][24]=75025LL,f[2][25]=121393LL;
	f[2][26]=196418LL,f[2][27]=317811LL,f[2][28]=514229LL;
	f[2][29]=832040LL,f[2][30]=1346269LL,f[2][31]=2178309LL;
	f[2][32]=3524578LL,f[2][33]=5702887LL,f[2][34]=9227465LL;
	f[2][35]=14930352LL,f[2][36]=24157817LL,f[2][37]=39088169LL;
	f[2][38]=63245986LL,f[2][39]=102334155LL,f[2][40]=165580141LL;
	f[2][41]=267914296LL,f[2][42]=433494437LL,f[2][43]=701408733LL;
	f[2][44]=1134903170LL,f[2][45]=1836311903LL,f[2][46]=2971215073LL;
	f[2][47]=4807526976LL,f[2][48]=7778742049LL,f[2][49]=12586269025LL;
	f[2][50]=20365011074LL,f[2][51]=32951280099LL,f[2][52]=53316291173LL;
	f[2][53]=86267571272LL,f[2][54]=139583862445LL,f[2][55]=225851433717LL;
	f[2][56]=365435296162LL,f[2][57]=591286729879LL,f[2][58]=956722026041LL;
	f[2][59]=1548008755920LL,f[2][60]=2504730781961LL,f[3][4]=11LL;
	f[3][6]=41LL,f[3][8]=153LL,f[3][10]=571LL;
	f[3][12]=2131LL,f[3][14]=7953LL,f[3][16]=29681LL;
	f[3][18]=110771LL,f[3][20]=413403LL,f[3][22]=1542841LL;
	f[3][24]=5757961LL,f[3][26]=21489003LL,f[3][28]=80198051LL;
	f[3][30]=299303201LL,f[3][32]=1117014753LL,f[3][34]=4168755811LL;
	f[3][36]=15558008491LL,f[3][38]=58063278153LL,f[3][40]=216695104121LL;
	f[4][4]=36LL,f[4][5]=95LL,f[4][6]=281LL;
	f[4][7]=781LL,f[4][8]=2245LL,f[4][9]=6336LL;
	f[4][10]=18061LL,f[4][11]=51205LL,f[4][12]=145601LL;
	f[4][13]=413351LL,f[4][14]=1174500LL,f[4][15]=3335651LL;
	f[4][16]=9475901LL,f[4][17]=26915305LL,f[4][18]=76455961LL;
	f[4][19]=217172736LL,f[4][20]=616891945LL,f[4][21]=1752296281LL;
	f[4][22]=4977472781LL,f[4][23]=14138673395LL,f[4][24]=40161441636LL;
	f[4][25]=114079985111LL,f[4][26]=324048393905LL,f[4][27]=920471087701LL;
	f[4][28]=2614631600701LL,f[4][29]=7426955448000LL,f[4][30]=21096536145301LL;
	f[5][6]=1183LL,f[5][8]=14824LL,f[5][10]=185921LL;
	f[5][12]=2332097LL,f[5][14]=29253160LL,f[5][16]=366944287LL;
	f[5][18]=4602858719LL,f[5][20]=57737128904LL,f[5][22]=724240365697LL;
	f[5][24]=9084693297025LL,f[6][6]=6728LL,f[6][7]=31529LL;
	f[6][8]=167089LL,f[6][9]=817991LL,f[6][10]=4213133LL;
	f[6][11]=21001799LL,f[6][12]=106912793LL,f[6][13]=536948224LL;
	f[6][14]=2720246633LL,f[6][15]=13704300553LL,f[6][16]=69289288909LL;
	f[6][17]=349519610713LL,f[6][18]=1765722581057LL,f[6][19]=8911652846951LL;
	f[6][20]=45005025662792LL,f[7][8]=1292697LL,f[7][10]=53175517LL;
	f[7][12]=2188978117LL,f[7][14]=90124167441LL,f[7][16]=3710708201969LL;
	f[8][8]=12988816LL,f[8][9]=108435745LL,f[8][10]=1031151241LL;
	f[8][11]=8940739824LL,f[8][12]=82741005829LL,f[8][13]=731164253833LL;
	f[8][14]=6675498237130LL,f[8][15]=59554200469113LL,f[9][10]=14479521761LL;
	f[9][12]=1937528668711LL,f[10][10]=258584046368LL,f[10][11]=3852472573499LL;
	f[10][12]=65743732590821LL;
}
int main(){
	get_V();
	while(scanf("%d%d",&x,&y)==2){
		if(x>y) swap(x,y);
		printf("%lld\n",f[x][y]);
	}
	return 0;
}

值得注意的是,long long赋值的时候建议加上LL后缀

还有,当m*n为奇数是由于全局变量默认为0,正好输出0

例三:

【训练题】错排问题

Description

  班里出了各淘气包,经常搞的老师哭笑不得。淘气包今天将班里每个同学的钥匙放在别人的橱柜里,这样每个人的橱柜里放着的都不是自己的钥匙。当然,也就都锁不上自己的橱柜了。

  老师对淘气包说:“你在考验老师,那么老师也考考你,好不好?”淘气包跃跃欲试,老师的问题是:淘气包这种放置钥匙的方法,会有多少种不同的情况呢?

Input

一个整数n:橱柜的个数即不同钥匙的个数(n<=12)

Output

一个整数:不同的方案数。

Sample Input 1 

3

Sample Output 1

2

Hint

n<=12

这道题其实是一个数学或动态规划(递推)题,面对n<=12的规模暴力排列生成超时,也可以打表

#include<iostream> 
#include<cstdio>
#include<algorithm>
using namespace std;
int a[20],n,ans[20]={0,0,1,2,9,44,265,1854,14833,133496,1334961,14684570,176214841};
/*
bool judge(int w){
	for(int i=1;i<=w;i++){
		if(a[i]==i) return false;
	}
	return true;
}
*/
int main(){
/*
递推方程分析:
1.分析:暴力枚举加打表 
2.现在我会分析了:f(i)=(i-1)(f(i-1)+f(i-2))
方法:设两个递推方程,消去一个就可以了
f(n+1)=n*g(n)    g(n)=(n-1)*g(n-1)+f(n-1) 
*/ 
/*
	for(int n=2;n<=12;n++){
		ans[n]=0;
		for(int i=1;i<=n;i++) a[i]=i;
		while(next_permutation(a+1,a+n+1)){
			if(judge(n)) ans[n]++;
		}
		printf("%d,",ans[n]);
	}
*/
	scanf("%d",&n);
	printf("%d\n",ans[n]);
	return 0;
}

其他应用:

a.生成小范围的素数表,欧拉函数表

b.生成某些需要的常数

### 回答1: 库首页开发技术是指在开发过程中使用的技术和方法,用于创建和维护一个库的主页。在库首页开发技术中,包括网页设计、前端开发、后端开发等方面的技术。 其他方面指的是除了库首页开发技术以外的其他技术和内容。在这个问题中,它指的是2017年的竞赛内容——数字万用表资料。 数字万用表是一种用来测量电压、电流、电阻等电气量的测量工具。它通过显示数字来表示测量结果,具有测量精度高、使用方便等特点。在2017年竞赛中,数字万用表资料指的是数字万用表的相关材料,包括原理图、PCB(印刷电路板)和源程序等内容。 原理图是用来描述数字万用表工作原理的图纸,在其中标识了各个部件之间的连接关系和工作原理。PCB则是数字万用表电路板的设计图,用来制作电路板,并将各个电子元件焊接上去。源程序是指用来控制数字万用表工作的程序代码,可以用来编写软件或固件。 这些资料在竞赛中被收藏,可能是因为这些资料对于参赛者来说非常有价值。参赛者可以通过研究这些资料来了解数字万用表的工作原理和设计方法,从而获得更好的成绩或解决问题的方法。因此,这些资料被收藏起来,方便参赛者随时查阅和借鉴。 ### 回答2: 库首页开发技术是指在开发电子设备时所使用的技术和工具。在2017年的竞赛中,数字万用表资料是指关于数字万用表的相关资料,包括原理图、pcb板设计和源程序代码等。 原理图是用于电子元件之间连接和工作原理的图纸。它显示了电子元件如何连接以及它们之间的功能关系。通过原理图,可以清晰地了解数字万用表的电路结构和信号流动。 PCB(Printed Circuit Board)是印刷电路板的简称,也是电子装置中不可或缺的组成部分。PCB板上绘制了电子元件的连接图,通过电路板上的导线和焊盘进行电子元件的连接。通过进行pcb板设计,可以制作出高质量的数字万用表电路板。 源程序是数字万用表的控制程序,通过编程语言编写。源程序决定了数字万用表的功能和操作方法。通过源程序,可以对数字万用表进行自定义的设置和功能扩展。 在竞赛中,使用数字万用表资料可以帮助参赛者更好地了解数字万用表的工作原理和电路结构,为他们的项目开发提供参考和指导。收藏2017年的数字万用表资料对于学习和研究电子技术以及提高自己的设计能力都非常有帮助。通过研究这些资料,能够帮助参赛者更好地了解数字万用表的原理和使用方法,为自己的电子产品的开发提供技术支持和灵感。 ### 回答3: 库首页开发技术是指以数字万用表为题材的开发技术。这项技术竞赛于2017年举行,主要涉及数字万用表的原理图、PCB设计和源程序的开发。参赛者需要通过设计和开发出一款具有高准确度和可靠性的数字万用表。 原理图是指数字万用表的电路原理图,通过原理图可以了解和分析万用表的电路结构、电路元件和信号流向等。原理图的设计需要基于相关原理和技术知识,以实现数字万用表的功能。 PCB设计是指将数字万用表的原理图转化为实际的电路板设计,包括电路连接、布局和细节等。PCB设计需要考虑到电路板的尺寸、信号传输路径、电源稳定性、抗干扰能力等因素,以确保数字万用表的正常运行。 源程序是指数字万用表的控制系统的开发代码,包括嵌入式软件编程、界面设计和硬件控制等。源程序需要满足数字万用表的各项功能和性能要求,确保准确度、稳定性和易用性。 收藏2017指的是这些竞赛项目的资料资源。通过收藏2017年的竞赛资料,可以进一步研究和了解数字万用表开发技术,对相关领域的学习和实践具有重要意义。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值