b_51_01组成的N的倍数(同余定理+bfs)

给定一个自然数N,找出一个M,使得M>0且M是N的倍数,并且M的10进制表示只包含0或1。求最小的M。
例如:N=4,M=100。(1<=N<=10^6)

思路:M只能有0/1,所以可以从1开始bfs,每次将队头的数×10+0/1可枚举到所有合法数字,但时耗很长,且会溢出,不可取
优化:M%N为0(M>0),则证明M是N的倍数,那我可以直接开一个结构体(string,int)记录M以及M%N的余数,用检查余数结果是否0来判断当前string M是否是N的倍数,证明:

假设 M_modN=M%N,又
(M×10+x)%N
=M×10%N+x%N
=M%N+x%N
=M_modN+x%N
所以将(M×10+x)%N压入队列等价于将M%N+x%N(即(M+x)%N)压入队列

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int vis[N];
struct node {
    string m;
    int r;
};
void bfs(int n) {
    queue<node> q;
    q.push({"1",1}), vis[1]=1;
    while (!q.empty()) {
        node t=q.front(); q.pop();
        if (t.r==0) {cout<<t.m; break;}
        for (int k=0; k<=1; k++) {
            int nr=(t.r*10+k)%n;
            if (!vis[nr]) {
                q.push({t.m+(k==0 ? '0' : '1'), nr}); //q.push({t.m+to_string(k), nr});
                vis[nr]=1;
            }
        }
    }
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int num; cin>>num;
    bfs(num);
    return 0;
}

这都超时?不会吧,将to_string改成拼接字符'0'/'1',快了800ms...

posted @ 2020-10-26 11:26  童年の波鞋  阅读(116)  评论(0编辑  收藏  举报