编程之美——2.8 找符合条件的整数

寻找满足条件的最小正整数M

题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0.


解决这个问题首先考虑对于任意的N,是否这样的M一定存在。可以证明,M是一定存在的,而且不唯一。
简单证明:因为

 

这是一个无穷数列,但是数列中的每一项取值范围都在[0, N-1]之间。所以这个无穷数列中间必定存在循环节。即假设有s,t均是正整数,且s<t,有 。于是循环节长度为t-s。于是10^s = 10^t。因此有:
,所以

例如,取N=3,因为10的任何非负次方模3都为1,所以循环节周期为1.有:

 

给定N,求M的方法:
方法一:给定N,令M从2开始,枚举M的值直到遇到一个M使得N*M的十进制表示中只有1和0.
方法二:求出10的次方序列模N的余数序列并找出循环节。然后搜索这个余数序列,搜索的目的就是要在这个余数序列中找到一些数出来让它们的和是N的倍数。例如N=13,这个序列就是1,10,9,12,3,4然后不断循环。很明显有1+12=13,而1是10的0次方,12是10的3次方,所以这个数就是1000+1=1001,M就是1001/13=77。
方法三:因为N*M的取值就是1,10,11,100,101,110,111,......所以直接在这个空间搜索,这是对方法一的改进。搜索这个序列直到找到一个能被N整除的数,它就是N*M,然后可计算出M。例如N=3时,搜索树如下:

上图中括号内表示模3的余数。括号外表示被搜索的数。左子树表示0,右子树表示1.上图中搜索到第二层(根是第0层)时遇到111,它模3余数为0.所以N*M=111, M=111/3=37。
方法四:对方法三的改进。将方法三的搜索空间按模N余数分类,使得搜索时间和空间都由原来的指数级降到了O(N)。改进的原理:假设当前正在搜索由0,1组成的K位十进制数,这样的K位十进制数共有2^k个。假设其中有两个数X、Y,它们模N同余,那么在搜索由0、1组成的K+1位十进制数时,X和Y会被扩展出四个数:10X, 10X+1, 10Y, 10Y+1。因为X和Y同余(同余完全可以看作相等),所以10X与10Y同余,10X+1与10Y+1同余。也就是说由Y扩展出来的子树和由X扩展产生出来的子树产生完全相同的余数,如果X比Y小,那么Y肯定不是满足要求的最小的数,所以Y这棵子树可以被剪掉。这样,2^K个数按照模N余数分类,每类中只保留最小的那个数以供扩展。原来在这一层需要搜索2^K个数,现在只需要搜索O(N)个数。例如,当N=9时,第0层是1(1),

如上图所示,第2层的110,第三层的1010、1110都因为同一层有和它同余且更小的数而被剪掉。如果按照方法三搜索,第三层本来应该有8个结点,但现在只有4个结点。

方法一的源代码:

    #include <stdio.h>  
      
    int HasOnlyOneAndZero(unsigned int n) {  
        while(n) {  
            if(n % 10 >= 2) return 0;  
            n /= 10;  
        }  
        return 1;  
    }  
      
    int main() {  
        int n, m;  
        while(scanf("%d", &n) != EOF) {  
            for(m = 1;;m++) {  
                if(HasOnlyOneAndZero(n*m)) {  
                    printf("n = %d, m = %d, n*m = %d/n", n, m, n*m);  
                    break;  
                }  
            }  
        }  
        return 0;  
    }  

方法三的源代码:

    // 解法三(1):广度优先搜索  
    #define _CRT_SECURE_NO_WARNINGS 1  
      
    #include <cstdio>  
    #include <queue>  
    using namespace std;  
      
    int main() {  
        int N;  
        while(scanf("%d", &N) != EOF) {  
            queue<int> q;  
            q.push(1);  
            while(!q.empty()) {  
                int t = q.front();  
                q.pop();  
                if(t % N == 0) {  
                    printf("n = %d, m = %d, n*m = %d/n", N, t/N, t);  
                    break;  
                }  
                q.push(t * 10);  
                q.push(t * 10 + 1);  
            }  
        }  
        return 0;  
    }  

方法四源代码:

    // 解法四:将搜索空间分过类的广度搜索,这样空间占用是O(N)而不是  
    // 指数级。分类的原则是按照模N的余数分类   
    #define _CRT_SECURE_NO_WARNINGS 1  
      
    #include <cstdio>  
    #include <bitset>  
    #include <vector>  
    #include <queue>  
    using namespace std;  
      
    struct QNode {  
        int v, r; // v is value, r is remainder  
        QNode(int vv, int rr): v(vv), r(rr) {}  
        QNode(): v(0), r(0) {}  
    };  
      
    int main() {  
        int N;  
        while(scanf("%d", &N) != EOF) {  
            //bitset<N> bn;  
            queue<QNode> q;  
            q.push(QNode(1, 1));  
            while(!q.empty()) {  
                //bn.reset();  
                vector<bool> bn(N, false);  
                int s = q.size();  
                while(s--) {  
                    QNode t = q.front();  
                    if(t.r == 0) {  
                        printf("n = %d, m = %d, n*m = %d/n", N, t.v/N, t.v);  
                        goto ok;  
                    }  
                    q.pop();  
                    if(!bn[t.r * 10 % N]) {  
                        bn[t.r * 10 % N] = true;  
                        q.push(QNode(t.v * 10, t.r * 10 % N));  
                    }  
                    if(!bn[(t.r * 10 + 1) % N]) {  
                        bn[(t.r * 10 + 1) % N] = true;  
                        q.push(QNode(t.v * 10 + 1, (t.r * 10 + 1) % N));  
                    }  
                }  
            }  
    ok:;  
        }  
        return 0;  
    }  



``` {—————————————— 系统参数模块(行业中性化处理) ——————————————} 行业代码:=HYBLOCK; DYNPETTM:=IF(FINANCE(33)>0, CLOSE/(FINANCE(33)/FINANCE(1)+0.0001), 1000); PB_RATIO:=IF(FINANCE(5)>0, CLOSE/FINANCE(5), 1000); PEG_VAL:=DYNPETTM/MAX(FINANCE(54)/FINANCE(34)*100,0.0001); {——估值参数行业分位数优化——} PETTM_QUANTILE:=DYNPETTM/REF(HHV(DYNPETTM,240),1); PB_QUANTILE:=PB_RATIO/REF(HHV(PB_RATIO,240),1); PEG_QUANTILE:=PEG_VAL/REF(HHV(PEG_VAL,240),1); {——波动率动态加权——} MA20:MA(CLOSE,20); MA60:MA(CLOSE,60); VOLATILITY:=EMA(STD(CLOSE,20)/MA20,5); VAR_PERIOD:=IF(VOLATILITY<0.06,55,IF(VOLATILITY<0.12,34,21))*0.6 + REF(VAR_PERIOD,1)*0.4; FAST_LEN:=CEILING(EMA(VAR_PERIOD*0.382,3)); SLOW_LEN:=FLOOR(EMA(VAR_PERIOD*1.618,3)); SGNL_LEN:=IF(VAR_PERIOD<=21,5,7); {—————————————— 核心指标模块(动量增强) ——————————————} {——MACD状态机——} DIF:=EMA(CLOSE,FAST_LEN) - EMA(CLOSE,SLOW_LEN); DEA:=EMA(DIF,SGNL_LEN); MACD:=2*(DIF-DEA); MACD_PHASE:=IF(DIF>DEA AND DEA>0,2,IF(DIF>DEA,1,IF(DIF<DEA AND DEA<0,-2,-1))); {——均线收敛系统——} MA5:=EMA(CLOSE,5); MA10:=EMA(CLOSE,10); MA_CONV:=ATAN(MA5/MA10)*180/3.1416; TREND_ARR:=MA5>MA10 AND MA10>MA20 AND MA20>MA60 AND MA_CONV>15; {——量价共振模型——} VOL_MA5:=MA(VOL,5); VOL_MA20:=EMA(VOL,20); VOL_SIG:=VOL>VOL_MA20*1.3 AND VOL>REF(HHV(VOL,5),1)*1.1 AND (CLOSE-OPEN)/(HIGH-LOW+0.0001)>0.5; {——动量状态检测——} MOMENTUM:=EMA(C,5)/REF(EMA(C,5),3)-1; WEEK_CHG:=(C-REF(C,5))/REF(C,5)*100; MOM_CONF:=EMA(C,5)>EMA(C,13) AND C>EMA(C,34)*1.05 AND WEEK_CHG>HHV(WEEK_CHG,20)*0.6; {—————————————— 信号合成模块(分时/盘后双模式) ——————————————} {——盘中异动预警——} INTRADAY_SIG:VOL>DYNAINFO(5)*1.5 AND (C-DYNAINFO(3))/DYNAINFO(3)*100>2.5 AND MACD_PHASE>=1 AND MOMENTUM>0.015 FILTER(CROSS(VOL_MA5,VOL_MA20),30); {——盘后主升浪选股——} VALUATION:=PETTM_QUANTILE<0.7 AND PB_QUANTILE<0.8 AND PEG_QUANTILE<0.9; TREND_SIG:=TREND_ARR AND BETWEEN(C/MA60,1.08,1.35); MOM_SIG:=MACD_PHASE>=1 AND MOM_CONF; PRICE_VOL:=VOL_SIG AND WEEK_CHG>5; {——风险过滤(行业适配)——} BETA_COEF:=SLOPE(C/INDEXC,60)*STD(C,60)/STD(INDEXC,60); DEBT_RATIO:=FINANCE(42)/FINANCE(1); CASH_RATIO:=FINANCE(10)/FINANCE(1); RISK_FLT:=IF(INSTR(行业代码,'银行|地产'),DEBT_RATIO<0.85 AND CASH_RATIO>0.15, DEBT_RATIO<0.55 AND CASH_RATIO>0.25); {——周期共振验证——} CY_MON:=MA(C,10)>REF(MA(C,10),5) AND MA(C,20)>REF(MA(C,20),10); CY_WK_DIFF:=EMA(C,10)-EMA(C,30); CY_WK_DEA:=EMA(CY_WK_DIFF,8); CY_WK:=CY_WK_DIFF>CY_WK_DEA AND CY_WK_DIFF>0; {——最终信号生成——} SCAN_SIG:VALUATION AND RISK_FLT AND CY_MON AND CY_WK AND COUNT(TREND_SIG AND MOM_SIG,5)>=2 AND WEEK_CHG>HHV(WEEK_CHG,20)*0.6; FINAL_SIGNAL:FILTER(SCAN_SIG,3),COLORGREEN;```你的身份是高级编程技术专家,精通各类编程语言,能对编程过程中的各类问题进行分析解答。我的问题是【我正在编辑【通达信量化择时周线选股】代码,我的选股逻辑是什么?用2015-2024年全A股验证选股逻辑的准确性,并提出优化建议方案,所有参数计算关系信号触发条件,是否选到股票市场情绪高即将启动主升浪的盘中异动股票,及日线盘中预警选股盘后选股,去除冗余选股条件】,请帮我检查并补全正确代码,生成修正后完整代码。
最新发布
03-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值