array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 USACO Section 1.3 Prime Cryptarithm 解题报告 - 爱码网

题目描述

牛式的定义,我们首先需要看下面这个算式结构:

      * * *
   x    * *
    -------
      * * *         <-- partial product 1
    * * *           <-- partial product 2
    -------
    * * * *

这是一个乘法结构,我们给出一个数字集合,例如{2,3,5,7},如果我们能够集合里面的数字代替所有的*,使得这个乘法成立的话,那么这就是一个牛式。对于给出的集合,我们需要找出总共有多少个牛式。

数据范围

集合中的数字只能是从{1,2,3,4,5,6,7,8,9}中挑选。

样例输入

第一行输入所给集合中元素个数,下一行写出集合中的元素

5
2 3 4 6 8

样例输出

1

解题思路

因为数据量不大,所以我直接用枚举的方式,产生每一个被乘数与乘数,然后判断是否它的所有位都是由集合中的元素组合的。枚举出所有的情况,然后统计符合条件的。

Tip: 我在编码实现的时候遇到一个问题,我在本地测试样例发现可以通过,输出是1,但是当我提交到USACO的判题系统上时,它给我的反馈是我的第一组样例输出为21,我总共提交了十几次,始终不知道是什么原因造成的。后来看了下官方的文档,发现有可能是数组越界...后来思考了很久,终于让我找到了代码的bug!总之,以后编码的时候一定要细心,这种小错误真的很浪费时间,如果真的在比赛中出现这种情况很有可能你就因此与奖牌失之交臂。

解题代码

/*
ID: yinzong2
PROG: crypt1
LANG: C++11
*/
#define MARK
#include<cstdio>
#include<set>
#include<cstdlib>
#include<algorithm>

using namespace std;

set<int> numSet;

int n, cnt;
int num[10];

bool test(int x, int length) {
    int a[10];//就是这个数组,最开始的时候我开小了,但是在本地样例可以过。
    int len = 0;
    while(x) {
        a[len++] = x%10;
        x /= 10;
    }
    if(len != length) return false;
    for(int i = 0; i < len; i++) {
        if(numSet.find(a[i]) == numSet.end()) {
            return false;
        }
    }
    return true;
}

//产生乘数
void makeMultiplier(int multiplier, int cur, int multiplicand) {
    if(cur >= 2) {
        int firstMul = (multiplier%10) * multiplicand;
        if(test(firstMul, 3)) {//判断是否符条件,应该是一个3位数
            int secondMul = (multiplier/10) * multiplicand;
            if(test(secondMul, 3)) {//同上
                int sum = secondMul*10 + firstMul;
                if(test(sum, 4)) {//同上,最后的和是4位的
                    cnt++;
                }
            }
        }
        return ;
    }
    for(int i = 0; i < n; i++) {
        multiplier += num[i];
        if(0 == cur) {
            multiplier *= 10;
        }
        makeMultiplier(multiplier, cur+1, multiplicand);
        //状态还原
        if(0 == cur) {
            multiplier /= 10;
        }
        multiplier -= num[i];
    }
}

//产生被乘数
void makeMultiplicand(int multiplicand, int cur) {
    if(cur >= 3) {
        makeMultiplier(0, 0, multiplicand);
        return ;
    }
    for(int i = 0; i < n; i++) {
        multiplicand += num[i];
        if(cur < 2) {
            multiplicand *= 10;
        }
        makeMultiplicand(multiplicand, cur+1);
        //状态还原
        if(cur < 2) {
            multiplicand /= 10;
        }
        multiplicand -= num[i];
    }
}

int main() {
#ifdef MARK
    freopen("crypt1.in", "r", stdin);
    freopen("crypt1.out", "w", stdout);
#endif // MARK
    while(~scanf("%d", &n)) {
        numSet.clear();
        for(int i = 0; i < n; i++) {
            scanf("%d", &num[i]);
            numSet.insert(num[i]);
        }
        cnt = 0;
        makeMultiplicand(0, 0);
        printf("%d\n", cnt);
    }
    return 0;
}

(2017.08.20增加该部分)上面这种写法其实不是很直接,很容易出错。我今天又重新写了一遍,我觉得代码应该以最符合直觉的状态呈现出来,这样就容易读,也容易写。虽然可能会稍微长一点,但是不会出错,基本一遍就能过。

/*
ID: yinzong2
PROG: crypt1
LANG: C++11
*/
#define MARK
#include <iostream>
#include <cstring>

using namespace std;

int n, cnt;
int collect[10], num1[5], num2[5], prod1[5], prod2[5], sum[5];

bool judge() {
    for (int i = 0; i < 3; ++i) {
        prod1[i] = num2[0]*num1[i];
        prod2[i] = num2[1]*num1[i];
    }
    prod1[3] = prod2[3] = 0;
    for (int i = 0; i < 3; ++i) {
        prod1[i+1] += (prod1[i]/10);
        prod1[i] = (prod1[i]%10);
        prod2[i+1] += (prod2[i]/10);
        prod2[i] = (prod2[i]%10);
    }
    if (prod1[3] != 0 || prod2[3] != 0) {
        return false;
    }
    sum[0] = prod1[0];
    for (int i = 1; i < 3; ++i) {
        sum[i] = prod1[i] + prod2[i-1];
    }
    sum[3] = prod2[2];
    sum[4] = 0;
    for (int i = 0; i < 4; ++i) {
        sum[i+1] += (sum[i]/10);
        sum[i] = sum[i]%10;
    }
    if (sum[4] != 0) {
        return false;
    }
    for (int i = 0; i < 3; ++i) {
        bool flag = false;
        for (int j = 0; j < n; ++j) {
            if (prod1[i] == collect[j]) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            return false;
        }
    }
    for (int i = 0; i < 3; ++i) {
        bool flag = false;
        for (int j = 0; j < n; ++j) {
            if (prod2[i] == collect[j]) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            return false;
        }
    }
    for (int i = 0; i < 4; ++i) {
        bool flag = false;
        for (int j = 0; j < n; ++j) {
            if (sum[i] == collect[j]) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            return false;
        }
    }
    return true;
}

void produce2(int cur) {
    if (cur == 2) {
        if (judge()) {
            cnt++;
        }
        return ;
    }
    for (int i = 0; i < n; ++i) {
        num2[cur] = collect[i];
        produce2(cur+1);
    }
}

void produce(int cur) {
    if (cur == 3) {
        produce2(0);
        return ;
    }
    for (int i = 0; i < n; ++i) {
        num1[cur] = collect[i];
        produce(cur+1);
    }
}

int main() {
#ifdef MARK
    freopen("crypt1.in", "r", stdin);
    freopen("crypt1.out", "w", stdout);
#endif // MARK
    while (cin>>n) {
        for (int i = 0; i < n; ++i) {
            cin >> collect[i];
        }
        cnt = 0;
        produce(0);
        cout << cnt << endl;
    }
    return 0;
}

解题思路(Type 2)

思路其实与上述保持一致,但是由于代码不简洁,在参考了大牛的代码之后,我准备重构一下代码。我们在枚举和判断的时候都可以写的更加优美,大牛毕竟是大牛。

解题代码(Type 2)

/*
ID: yinzong2
PROG: crypt1
LANG: C++11
*/
#define MARK
#include<cstdio>
#include<cstring>
#include<cstdlib>

using namespace std;

int n;
int numSet[10];
bool vis[10];

bool ok(int x) {
    while(x) {
        if(!vis[x%10]) return false;
        x /= 10;
    }
    return true;
}

bool test(int a, int b, int c, int d, int e) {
    int first = a*100 + b*10 + c;
    int mul1 = e * first;
    int mul2 = d * first;
    int sum = mul2 * 10 + mul1;
    if(mul1 < 100 || mul1 > 999) return false;
    if(mul2 < 100 || mul2 > 999) return false;
    if(sum < 1000 || sum > 9999) return false;
    return ok(mul1) && ok(mul2) && ok(sum);
}

int main() {
#ifdef MARK
    freopen("crypt1.in", "r", stdin);
    freopen("crypt1.out", "w", stdout);
#endif // MARK
    while(~scanf("%d", &n)) {
        memset(vis, false, sizeof(vis));
        for(int i = 0; i < n; i++) {
            scanf("%d", &numSet[i]);
            vis[numSet[i]] = true;
        }
        int a,b,c,d,e;
        int cnt = 0;
        for(int i = 0; i < n; i++) {
            a = numSet[i];
            for(int j = 0; j < n; j++) {
                b = numSet[j];
                for(int k = 0; k < n; k++) {
                    c = numSet[k];
                    for(int p = 0; p < n; p++) {
                        d = numSet[p];
                        if((a*d) >= 10) continue;//会产生一个四位数,剪枝
                        for(int q = 0; q < n; q++) {
                            e = numSet[q];
                            if((a*e) >= 10) continue;//会产生一个四位数,剪枝
                            if(test(a,b,c,d,e)) {
                                cnt++;
                            }
                        }
                    }
                }
            }
        }
        printf("%d\n", cnt);
    }
    return 0;
}

相关文章: