sakiko的排列构造
题目大意:
有一个排列p,对于i属于1-n,pi = pi+i,且pi要是质数
easy和hard不同就只有n的范围
1<=n<=1e6
分析:
尝试之后发现,找到离pi最近的质数,就会有一溜数可以放好,然后便是规模更小的问题,例如 n = 7,最近的质数是11
,那么7放第4个,6放第5个直到4放第7个,剩下的是n = 3的问题。还有考虑有没有解这个问题,质数有个性质:对于a(>1),在a-2a之间必定存在一个质数,可以保证有解
可能是我太弱了,写的打表+二分没有暴力快
G
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n;
int v[1000080],prime[1000080],cnt=0;
int ans[1000010];
int find(int x){
int l = 1,r = cnt;
while(l<=r){
int mid = (l+r)>>1;
if(x<prime[mid]) r = mid-1;
else l = mid+1;
}
return prime[l];
}
int main(){
ios;
cin>>n;
for(int i = 2;i<=n*2;++i){
if(v[i]==0){
v[i]=i;
prime[++cnt]=i;
}
for(int j = 1;j<=cnt;++j){
if(prime[j]>v[i]||i*prime[j]>n*2) break;
v[i*prime[j]]=prime[j];
}
}
int i = n;
while(i>0){
int minp = find(i);
for(int j = minp-i;j<=i;++j) ans[j] = minp-j;
i = minp-i-1;
}
for(int i = 1;i<=n;++i) cout<<ans[i]<<" ";
return 0;
}
H
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n;
int ans[1000070];
bool isprime(int x){
if(x==1) return 0;
for(int i = 2;i*i<=x;++i){
if(x%i==0) return 0;
}
return 1;
}
void solve(){
cin>>n;
int i = n;
while(i>0){
int minp = i+1;
while(!isprime(minp)) minp++;
//cout<<minp<<" "<<l<<"\n";
for(int j = i;j>=minp-i;--j) ans[j] = minp-j;
i=minp-i-1;
}
for(int i = 1;i<=n;++i) cout<<ans[i]<<" ";
cout<<"\n";
}
int main(){
ios;
int t=1;
//cin>>t;
while(t--){
solve();
}
return 0;
}
当然H也可以过G