Project Euler 32 Pandigital products


题意:找出所有形如 39 × 186 = 7254 这种,由 1 ~ 9,9个数字构成的等式的和,注意相同的积不计算两次

思路:如下面两种方法


方法一:暴力枚举间断点

/*************************************************************************
    > File Name: euler032.cpp
    > Author:    WArobot 
    > Blog:      http://www.cnblogs.com/WArobot/ 
    > Created Time: 2017年05月24日 星期三 20时08分07秒
 ************************************************************************/

#include <stdio.h>
#include <inttypes.h>
#include <set>
#include <algorithm>

int32_t CalNum(int32_t s,int32_t e,int32_t* num){   // 计算[s,e]之间num值
    int32_t sum = 0;
    for(int32_t i = s ; i <= e ; i++)   sum = sum * 10 + num[i];
    return sum;
}
bool check(int32_t x1,int32_t x2,int32_t* num){     // 判断是否符合题意
    int tmp1 = CalNum(0,x1,num) , tmp2 = CalNum(x1+1,x2,num) , tmp3 = CalNum(x2+1,8,num);
    return tmp1 * tmp2 == tmp3;
}
void solve(){
    int32_t num[9] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
    std::set<int32_t> st;                           // 采用set去重 
    do{
        for(int32_t i = 0 ; i < 6 ; i++){
            for(int32_t j = i + 1 ; j < 8 ; j++){
                if( check( i , j , num ) ){         // 暴力枚举两个间断点的位置
                    st.insert( CalNum( j + 1 , 8 , num ) );
                }
            }
        }
    }while( std::next_permutation( num , num + 9 ) );

    int32_t sum = 0;
    std::set<int32_t>::iterator it;
    for( it = st.begin(); it != st.end() ; it++)    sum += *it;
    printf("%d\n",sum);
}
int main(){
    solve();
    return 0;
}

方法二:暴力枚举出 a 、b ,判断是否符合题意

/*************************************************************************
    > File Name: euler032t2.c
    > Author:    WArobot 
    > Blog:      http://www.cnblogs.com/WArobot/ 
    > Created Time: 2017年06月24日 星期六 21时55分16秒
 ************************************************************************/

#include <stdio.h>
#include <math.h>
#include <inttypes.h>

#define MAX_N 10000000

int32_t canAdd[ MAX_N + 1 ] = {0};

int32_t HowManyDigs(int32_t i , int32_t j) {
    int32_t digs = 0;
    digs += (int32_t)log10( i ) + 1;
    digs += (int32_t)log10( j ) + 1;
    digs += (int32_t)log10( i * j ) + 1;
    return digs;
}
bool AppearOnce(int32_t x , int32_t* num) {
    while(x) {
        if( ( x % 10 == 0 ) || ( num[  x % 10 - 1 ] ) ) return false;
        num[ x % 10 - 1 ] = 1;
        x /= 10;
    }
    return true;
}
bool IsDigital(int32_t a , int32_t b) {
    int32_t num[9] = {0};
    bool ok = true;
    ok = ( ok && AppearOnce(a,num) );
    ok = ( ok && AppearOnce(b,num) );
    ok = ( ok && AppearOnce(a*b,num) );
    return ok;
}
void solve() {
    int32_t sum = 0;
    for(int32_t i = 1 ; i < 100 ; i++) {
        for(int32_t j = i + 1 ; ; j++) {
            int32_t digs = HowManyDigs( i , j );
            if( digs < 9 )  continue;
            if( digs > 9 )  break;
            if( IsDigital( i , j ) && !canAdd[i*j] ) {
                sum += i * j;
                canAdd[ i * j ] = 1;
            }
        }
    }
    printf("%d\n",sum);
}
int32_t main() {
    solve();
    return 0;
}

转载于:https://www.cnblogs.com/WArobot/p/7074677.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值