URAL 1495 One-two, One-two 2

URAL 1495

思路:

折半枚举+高精度技巧。

先dfs枚举出小于等于15位的情况。

dp[i]表示余数为i的最小的数。

_dp[i]表示余数为i正好15的数。

然后枚举余数i,把它乘以1e15再模n后得到t,然后找_dp[n-t]

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))

const int N=1e6+5;
const ll INF=0x3f3f3f3f3f3f3f3f;
ll dp[N],_dp[N];
int n;
void dfs(ll num,int deep){
    if(num){
        dp[num%n]=min(dp[num%n],num);
        if(deep==15){
            _dp[num%n]=min(_dp[num%n],num);
            return ;
        }
    }
    dfs(num*10+1,deep+1);
    dfs(num*10+2,deep+1);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    mem(dp,INF);
    mem(_dp,INF);
    dfs(0,0);
    if(dp[0]!=INF){
        cout<<dp[0]<<endl;
        return 0;
    }
    ll sum1=0,sum2=0;
    for(int i=0;i<n;i++){
        if(dp[i]==INF)continue;
        ll t=i;
        for(int j=0;j<15;j++)t=(t*10)%n;
        ll x=n-t;
        if(_dp[x]==INF)continue;
        if(sum1==0||dp[i]<sum1){
            sum1=dp[i];
            sum2=_dp[x];
        }
    }
    if(sum1)cout<<sum1<<sum2<<endl;
    else cout<<"Impossible"<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/widsom/p/8378922.html