素数表

2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 , 41 , 43 , 47 , 53 , 59 , 61 … \large 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61\dots 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61

乘到 29 29 29(一共10项) ,乘积约为 6.47 × 1 0 9 6.47\times 10^9 6.47×109 i n t int int

乘到 53 53 53(一共16项),乘积约为 3.26 × 1 0 19 3.26\times 10^{19} 3.26×1019 l o n g   l o n g long \ long long long

反素数

反素数的性质:

  • 是从最小的质因数 2 2 2开始的连续质数乘积
  • x = p 1 k 1 p 2 k 2 … p m k m , k 1 ≥ k 2 ≥ k 3 ⋯ ≥ k m \large x=p_1^{k_1}p_2^{k_2}\dots p_m^{km},k_1\ge k_2\ge k_3\dots\ge k_m x=p1k1p2k2pmkm,k1k2k3km
1. d ( x ) = n d(x)=n d(x)=n的最小 x x x

根据质因数分解定理,考虑如何构造 x x x

采用搜索+剪枝。

反素数和素数表_c++

int p[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
ll ans=1e18;
int mx=15,n;
void dfs(ll x,int cnt,int dep,int up){
	if(ans>x&&cnt==n) ans=x;
	if(cnt>=n||dep>=mx) return;
	for(int i=1;i<=up;i++){
		if(x>ans/p[dep]||cnt*(i+1)>n) return;
		x*=p[dep];
		if(n%(cnt*(i+1))==0) dfs(x,cnt*(i+1),dep+1,i);
	}
}
int main(){
	scanf("%d",&n);
	dfs(1,1,0,60);
	printf("%lld\n",ans);
	return 0;
}
2.求 m a x {   d ( i )   } , i ∈ [ 1 , n ] \large max\{\ d(i)\ \},i\in[1,n] max{ d(i) },i[1,n],且 i i i尽可能小。

与上面方法同理。

int p[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
ll ans;
int mx=15,tot;
ll n;
void dfs(ll x,int cnt,int dep,int up){
	if(tot<cnt||tot==cnt&&x<ans) ans=x,tot=cnt;
	if(dep>=mx) return;
	for(int i=1;i<=up;i++){
		if(x>n/p[dep]) return;
		x*=p[dep];
		dfs(x,cnt*(i+1),dep+1,i);
	}
}
int main(){
	int t;scanf("%d",&t);
	while(t--){
	scanf("%lld",&n);ans=1e18,tot=0;
	dfs(1,1,0,60);
	printf("%lld %lld\n",ans,tot);
	}
	return 0;
}
P1463 [POI2002][HAOI2007]反素数

上题的弱化版

// Problem: P1463 [POI2002][HAOI2007]反素数
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1463
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-07-16 11:12:57
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
ll ans,tot;
ll n;
int p[]={2,3,5,7,11,13,17,19,23,29};
void dfs(ll x,int c,int dep,int up){
	if(tot<c||tot==c&&x<ans) ans=x,tot=c;
	if(dep>=10) return;
	for(int  i=1;i<=up;i++){
		if(x>n/p[dep]) return;
		x*=p[dep];
		dfs(x,c*(i+1),dep+1,i);
	}
}
int main(){
	scanf("%lld",&n);
	dfs(1,1,0,30);
	printf("%lld\n",ans);
	return 0;
}

P1574 超级数

在问题2的基础上,多组询问 q ≤ 1 0 5 q\le 10^5 q105

因为询问较多,实际上 [ 1 , 1 0 18 ] [1,10^{18}] [1,1018]之间的反素数是很少的,只有 155 155 155个。

因为可以先与出来,然后再每次二分查找。

int p[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
ll ans;
int mx=15,tot;
ll n;
void dfs(ll x,int cnt,int dep,int up){
	if(tot<cnt||tot==cnt&&x<ans) ans=x,tot=cnt;
	if(dep>=mx) return;
	for(int i=1;i<=up;i++){
		if(x>n/p[dep]) return;
		x*=p[dep];
		dfs(x,cnt*(i+1),dep+1,i);
	}
}
ll a[N];
ll b[N];
int id;
int main(){
	int m;
	scanf("%d",&m);
	for(int i=1;i<=m;i++) scanf("%lld",&a[i]),n=max(n,a[i]);
	n=1e18;
	while(n>1){
		ans=1e18,tot=0;
		dfs(1,1,0,60);
		b[++id]=ans;
		n=ans-1;
	}
	sort(b+1,b+id+1);
	for(int i=1;i<=m;i++){
		int x=upper_bound(b+1,b+id+1,a[i])-b-1;
		printf("%lld\n",b[x]);
	}
	return 0;
}
3.区间 [ l , r ] [l,r] [l,r]的反素数

改为枚举不同的质数。

维护当前已经得到的因子数 f r o m from from,当前枚举的质数 c u r cur cur,和当前枚举的质数的个数 c c c,当前的数 x x x

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e6+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
bitset<N>vis;
int p[N],cnt;
void ss(int n){
	vis[0]=vis[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]) p[++cnt]=i;
		for(int j=1;j<=cnt&&i*p[j]<=n;j++){
			vis[i*p[j]]=1;
			if(i%p[j]==0) break;
		}
	}
}
ll ans,l,r,mx;
ll ksm(ll a,ll n){
	ll ans=1;
	while(n){
		if(n&1) ans=ans*a;
		a=a*a;
		n>>=1;
	}
	return ans;
}
void dfs(int cur,int c,ll x,ll from){
	ll t=from*(c+1);
	if(x>=l&&(t>mx||t==mx&&ans>x)) ans=x,mx=t;
	for(int i=cur;i<=cnt;i++){
		if(x>r/p[i]) return;
		ll tmp=x*p[i];
		if(i==cur) dfs(cur,c+1,tmp,from);
		else {
			t=from*(c+1);
			ll q=(ll) log(r/x)/log(p[cur]);	// x * p[cur]^q <= r
			ll add=t*ksm(2,q); 
			//放缩 比p[cur]大的质数都放缩成p[cur] 这样每个数贡献2 就是2^q
			//如果放缩之后还比mx小直接返回
			if(add<mx) return;
			if((l-1)/x==r/x) return;//如果区间内没有该数的倍数直接返回
			if(x<r/p[cnt]){	// 特殊情况  [l,r]=[p^2,p^2] ,p是一个大素数.
				if(t*2>mx){
					ans=r;
					mx=t*2;
				}
			}
			dfs(i,1,tmp,t);
		}
	}
}
int main(){
	ss(N-5);
	scanf("%lld%lld",&l,&r);
	dfs(1,0,1,1);
	printf("%lld\n",mx);
	return 0;
}

小明系列故事——未知剩余系

任务1,求满足 d ( n ) = n − k d(n)=n-k d(n)=nk,最小 n n n,可以用递推筛一下。

void init(){
	for(int i=1;i<N;i++) d[i]=i ;
	for(int i=1;i<N;i++){
		for(int j=i;j<N;j+=i) d[j]--;
		if(!d[d[i]]) d[d[i]]=i; //第一次找到
		d[i]=0;//每次初始化为没找到.
	}
}

任务2就是反素数的裸题了。

ll ans;
int p[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
int mx=15,n;
void dfs(ll x,int c,int dep,int up){
	if(c==n&&x<ans) ans=x;
	if(c>=n||dep>=mx) return;
	for(int i=1;i<=up;i++){
		if(x>ans/p[dep]||c*(i+1)>n) return;
		x*=p[dep];
		if(n%(c*(i+1))==0) dfs(x,c*(i+1),dep+1,i);
	}
}
Who Gets the Most Candies? 线段树&反素数

预处理反素数+线段树模拟

单点查询后删除,就是约瑟夫环。

// Problem: Who Gets the Most Candies?
// Contest: POJ - POJ Monthly--2006.07.30
// URL: http://poj.org/problem?id=2886
// Memory Limit: 131 MB
// Time Limit: 5000 ms
// Date: 2021-07-16 14:52:08
// --------by Herio--------

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=5e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
PII a[N];
int ans,tot,cnt;
int p[15]={2,3,5,7,11,13,17,19,23,29};
char name[N][50];
int num[N];
int n,k;
void dfs(int x,int c,int d,int up){
	if(c>tot||c==tot&&x<ans) ans=x,tot=c;
	if(d>=10) return;
	for(int i=1;i<=up;i++){
		if(x>n/p[d]) return;
		x*=p[d];
		dfs(x,c*(i+1),d+1,i);
	}
}
#define lx x<<1
#define rx x<<1|1
struct node{
	int l,r,s;
}b[N<<2];
void re(int x){
	b[x].s=b[lx].s+b[rx].s;
}
void bud(int x,int l,int r){
	b[x].l=l,b[x].r=r,b[x].s=0;
	if(l==r){
		b[x].s=1;
		scanf("%s %d",name[l],&num[l]);
		return;
	}
	int m=l+r>>1;
	bud(lx,l,m),bud(rx,m+1,r);
	re(x);
}
int que(int x,int v){
	if(b[x].l==b[x].r){
		b[x].s=0;
		return b[x].l;
	}
	int ans;
	if(v<=b[lx].s) ans=que(lx,v);
	else ans=que(rx,v-b[lx].s);
	re(x);
	return ans;
}
int main(){
	n=1e9;
	a[++cnt]={1,1};
	while(n>1){
		ans=1e9,tot=0;
		dfs(1,1,0,30);
		a[++cnt]={ans,tot};
		n=ans-1;
	}
	sort(a+1,a+cnt+1);
	//for(int i=1;i<=cnt;i++) printf("%d %d\n",a[i].fi,a[i].se);
	while(~scanf("%d%d",&n,&k)){
	bud(1,1,n);
	int id=1;
	while(a[id].fi<=n) id++;
	id--;
	int mx=a[id].se;
	int sz=n,pos;
	id=a[id].fi;
	while(id--){
		pos=que(1,k);
		sz--;
		if(!sz) break;
		if(num[pos]>=0){
			k=(k-1+num[pos])%sz;
		}
		else k=((k+num[pos])%sz+sz)%sz;
		if(!k) k=sz;
	}
	printf("%s %d\n",name[pos],mx);
	}
	return 0;
}