前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >打表法——暴力破解方法之一

打表法——暴力破解方法之一

作者头像
可定
发布2020-04-20 15:13:45
2.3K0
发布2020-04-20 15:13:45
举报
文章被收录于专栏:细嗅蔷薇

打表常见的做法

  • 在程序中一次性计算出所有用到的结果,之后的查询直接取这些结果。(最常用)
  • 在程序B中分一次或多次计算出所有需要用到的结果,手动把结果写在程序A的数组中,然后在程序A中就可以直接使用这些结果。

使用场景:从程序的一部分过程的消耗时间过多,或是没有想到好的算法,因此可以在另外一个程序中使用暴力算法求出结果。

  • 对一些不会做的题目,先用暴力程序计算小范围数据的结果,然后找规律,或许能找出答案。

使用场景:在数据范围大时容易用到。

例题

P1149 火柴棒等式

例一:P1149 火柴棒等式

这道题n<=20完全可以打表,使用打表法中的第一个方法。

代码(生成答案):

代码语言:javascript
复制
#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;
}

提交代码:

代码语言:javascript
复制
#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 个 12 的骨牌铺满,请计算有多少种铺法。”我们知道这个问题可用递推算法来解决,递推方程如下:    d1=1;    d2=2;    dn=dn-1+dn-2   _现在我们把这个问题推广一下:“有 m 行 n 列的长方形,用 (m_n)/2 个 1*2 的骨牌铺满,请计算有多少种铺法。

Input

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

Output

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

Sample Input 1

代码语言:javascript
复制
    1 2
    1 3
    1 4
    2 2
    2 3
    2 4
    2 11
    4 11

Sample Output 1

代码语言:javascript
复制
    1
    0
    1
    2
    3
    5
    144
    51205

Hint

m*n<=121

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

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

代码语言:javascript
复制
#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到程序中就可以了:

代码语言:javascript
复制
#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

列举一些常用的表:

1.素数表

2.阶乘表

3.逆元表

当然打表并不一定要直接初始化,也可以通过线性筛/递推打出。

参考

信息竞赛--打表法讲解

暴力&打表

版权所有:可定博客 © WNAG.COM.CN

本文标题:《打表法——暴力破解方法之一》

本文链接:https://cloud.tencent.com/developer/article/1616947

特别声明:除特别标注,本站文章均为原创,本站文章原则上禁止转载,如确实要转载,请电联:wangyeuuu@qq.com,尊重他人劳动成果,谢过~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 打表常见的做法
  • 例题
    • P1149 火柴棒等式
      • 参考
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档