math解题报告

来源:互联网 发布:flicker free mac 编辑:程序博客网 时间:2024/05/27 12:21

在Sak同学的热心帮助下,终于成功的搞清了0.0
手动@Sak
[建议先看程序后看我的文字。。]
由于维数包括 当前位数、原数每位之和、原数*d每位之和、 *d后的进位, 维数太多了存不下,又要判断是否计算过这样由四维组成的状态,只好用起了位运算。
f[i][j][k]表示 运算到第i位 s1剩j s2剩k下=时 的一个二进制数(二进制是为了判重用。)
place[]存放的是一个可以改变f[i][j][k]某一位上的数字(0变1,1还是1,巧妙地运用“|”[按位或])的二进制。将f[i][j][k] |= place[l]即可改变。
判断是否找过这四维组成的状态可以:
if(f[i][j][k] & place[l] == 1)说明是计算过的,这个想想就清楚啦!

整个过程就是最高位找起(最高位比较特殊不能为0嘛,在主程序搜,dfs内部就是找剩余位上的)dfs的第四维也就是每个for(int j = 0; j < 9; j++)是枚举*d后的进位j/more,至于为什么进位只有0~8也是因为最大9×9只有81嘛,只能进8啦。。

这个程序设计不得不说真心巧妙和高端,佩服的五体投地。
考试有这样清晰的思维很羡慕。
以下是代码(嘘!)

#include<iostream>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;const int maxn=1e2+5,maxs=10*maxn;const short place[]={1<<0,1<<1,1<<2,1<<3,1<<4,1<<5,1<<6,1<<7,1<<8,1<<9,1<<10};int n,s1,s2,d;int x[maxn];short f[maxn][maxs][maxs];int dfn_clock;int flag;void dfs(int pos,int rest1,int rest2,int more){    if(flag) return;    if(rest1<0||rest2<0||rest1>9*pos||rest2>9*pos||(f[pos][rest1][rest2]&place[more])) return;    if(!pos){        if(more){            f[pos][rest1][rest2]|=place[more];            return;        }        for(int i=n;i;--i) printf("%d",x[i]);        puts("");        flag=1;return;    }    for(int i=0;i<10;++i){        x[pos]=i;        for(int j=0;j<9;++j) if((i*d+j)/10==more) dfs(pos-1,rest1-i,rest2-(i*d+j)%10,j);    }    f[pos][rest1][rest2]|=place[more];}int main(){    freopen("math.in","r",stdin);    freopen("math.out","w",stdout);    scanf("%d%d%d%d",&n,&s1,&s2,&d);    for(int i=1;i<10;++i){        x[n]=i;        for(int j=0;j<9;++j) dfs(n-1,s1-i,s2-(i*d+j)/10-(i*d+j)%10,j);    }    if(!flag) puts("Cirno is too smart");    return 0;}
原创粉丝点击