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;
}