AT1489 文字列と素数(质数检验)

AT1489 文字列と素数(质数检验)

题目链接(洛谷):https://www.luogu.com.cn/problem/AT1489
题解:一看数据大小可以达到 1 e 10 1e10 1e10 的程度,第一时间就想到了Miller_Rabin素性检验(下文简称MR)。正常MR的适用范围可达到 1 e 18 1e18 1e18 ,并且时间复杂度也只有 O ( l o g n ) O(logn) O(logn) 。那么我们只要暴力求出字符串的所有对应数字的情况即可。使用unordered_map<char,int> ms记录一个字符正在对应的数字,unordered_map<int,int> mp记录一个数字是否已经被选用过,然后我们的dfs利用好这两个参数即可。
下面是AC代码。

#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
#define debug(x) cerr<<#x<<":"<<x<<endl
#define debug2(x,y) cerr<<#x<<":"<<x<<"  "<<#y<<":"<<y<<endl
#define debug3(x,y,z) cerr<<#x<<":"<<x<<"  "<<#y<<":"<<y<<"  "<<#z<<":"<<z<<endl
struct fastio{
    fastio(){
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
    }
}fio;
namespace number_theory{
    typedef long long ll;
    ll prime[6]={2,3,5,7,233,331};
    inline ll qmul(ll x, ll y, ll mod){return (x*y-(ll)(x/(long double)mod*y+1e-3)*mod+mod)%mod;}
    inline ll qpow(ll a, ll b, ll mod){ll res=1;while(b){if(b&1)res=qmul(res,a,mod);a=qmul(a,a,mod);b>>=1;}return res;}
    bool MR(ll n){
        if(n==2) return 1;
        if(n<2||!(n&1)) return 0;
        ll s=n-1;
        while(!(s&1)) s>>=1;
        for(int i=0;i<6;++i){
            if(n==prime[i]) return 1;
            ll t=s, m=qpow(prime[i],s,n);
            while(t!=n-1&&m!=1&&m!=n-1){
                m=qmul(m,m,n);
                t<<=1;
            }
            if(m!=n-1&&!(t&1)) return 0;
        }
        return 1;
    }
}
using namespace number_theory;
string s;
ll dfs(int pos,ll st,unordered_map<char,int>& ms,unordered_map<int,int>& mp){
    if(pos>=s.size()){
        if(MR(st)) return st;
        return -1;
    }
    if(ms.count(s[pos])) return dfs(pos+1,st*10+ms[s[pos]],ms,mp);
    for(int i=1;i<=9;i+=2){
        if(mp.count(i)) continue;
        ms[s[pos]]=i;
        ++mp[i];
        ll res=dfs(pos+1,st*10+i,ms,mp);
        if(res!=-1) return res;
        mp.erase(i);
    }
    ms.erase(s[pos]);
    return -1;
}
signed main(){
    unordered_map<char,int> ms;
    cin>>s;
    for(auto i:s) ++ms[i];
    if(ms.size()>5){
        cout<<-1<<endl;
        return 0;
    }
    ms.clear();
    unordered_map<int,int> mp;
    cout<<dfs(0,0,ms,mp)<<endl;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值