1. 程式人生 > 實用技巧 >b_51_01組成的N的倍數(同餘定理+bfs)

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...