2019年我能变强组队训练赛第一场

Array Without Local Maximums

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int maxn=100001;
const ll mod=998244353;
int n,a[maxn];
ll f[maxn][201][3],sum,ans;
int main()
{
    scanf("%d",&n);
    for (int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
    }
    for (int i=1; i<=200; i++)
    {
        if (a[1]!=-1&&a[1]!=i)
        {
            f[1][i][0]=f[1][i][1]=f[1][i][2]=0;
        }
        else
        {
            f[1][i][0]=1;
            f[1][i][1]=0;
            f[1][i][2]=0;
        }
    }
    for (int i=2; i<=n; i++)
    {
        sum=0;
        for (int j=1; j<=200; j++)
        {
            if (a[i]!=-1&&a[i]!=j)
            {
                f[i][j][0]=0;
            }
            else
            {
                f[i][j][0]=sum;
            }
            sum=(sum+f[i-1][j][0]+f[i-1][j][1]+f[i-1][j][2])%mod;
        }
        for (int j=1; j<=200; j++)
        {
            if (a[i]!=-1&&a[i]!=j)
            {
                f[i][j][1]=0;
            }
            else
            {
                f[i][j][1]=(f[i-1][j][0]+f[i-1][j][1]+f[i-1][j][2])%mod;;
            }
        }
        sum=0;
        for (int j=200; j>=1; j--)
        {
            if (a[i]!=-1&&a[i]!=j)
            {
                f[i][j][2]=0;
            }
            else
            {
                f[i][j][2]=sum;
            }
            sum=(sum+f[i-1][j][1]+f[i-1][j][2])%mod;
        }
    }
    for (int i=1; i<=200; i++)
    {
        ans=(ans+f[n][i][2]+f[n][i][1])%mod;
    }
    printf("%lld
",ans);
}

Shell Pyramid

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll i,j,k,n;
  
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&n) ;
        i = (ll)(pow(double(n) * 6.0,1.0/3.0))-1;
        while(i*(i+1)/2*(i+2)/3 < n )
        {
            i ++ ;
        }
        n -= (i-1)*(i)/2*(i+1)/3 ;
        j = (ll)(sqrt(n * 2.0)) ;
        while(j * (j+1)/2 < n)
            j ++ ;
        n -=j*(j-1)/2 ;
        k= n;
        printf("%lld %lld %lld
",i,j,k) ;
    }
    return 0;
}

Gauss Elimination

import java.util.*;
import java.math.*;
 
public class Main
{
    public static BigInteger g[][] = new BigInteger[110][110];
 
    public static boolean Gauss_Elimination(int n)
    {
        BigInteger tmp,a,b;
        int i,j,k;
        for (i=0; i<n; i++)
        {
            for (j=i; j<n; j++)
            {
                if (g[j][i].compareTo(BigInteger.ZERO)!=0)
                {
                    break;
                }
            }
            if (j>=n)
            {
                return false;
            }
            if (i!=j)
            {
                for (k=0; k<=n; k++)
                {
                    tmp=g[i][k];
                    g[i][k]=g[j][k];
                    g[j][k]=tmp;
                }
            }
            a=g[i][i];
            for (j=i+1; j<n; j++)
            {
                if (g[j][i].compareTo(BigInteger.ZERO)!=0)
                {
                    b=g[j][i];
                    for (k=i; k<=n; k++)
                    {
                        g[j][k]=g[j][k].multiply(a).subtract(g[i][k].multiply(b));
                    }
                }
            }
        }
        return true;
    }
    public static void main (String[] args)
    {
        Scanner cin = new Scanner(System.in);
        BigInteger x[]= new BigInteger[110];
        BigInteger y[]= new BigInteger[110];
 
        BigInteger tmp,up,down;
 
        int n,i,j;
 
        boolean neg;
 
        while (cin.hasNext())
        {
            n=cin.nextInt();
            for (i=0; i<n; i++)
            {
                for (j=0; j<=n; j++)
                {
                    g[i][j]=cin.nextBigInteger();
                }
            }
            if (Gauss_Elimination(n))
            {
                for (i=n-1; i>=0; i--)
                {
                    up=BigInteger.ZERO;
                    down=BigInteger.ONE;
                    for (j=i+1; j<n; j++)
                    {
                        up=y[j].multiply(up).add(g[i][j].multiply(x[j].multiply(down)));
                        down=y[j].multiply(down);
                    }
                    up=g[i][n].multiply(down).subtract(up);
                    down=g[i][i].multiply(down);
                    if (up.multiply(down).compareTo(BigInteger.ZERO)<0)
                    {
                        neg=true;
                    }
                    else
                    {
                        neg=false;
                    }
                    up=up.abs();
                    down=down.abs();
                    tmp=up.gcd(down);
                    x[i]=up.divide(tmp);
                    y[i]=down.divide(tmp);
                    if (neg)
                    {
                        x[i]=x[i].negate();
                    }
                }
                for (i=0; i<n; i++)
                {
                    if (x[i].mod(y[i]).compareTo(BigInteger.ZERO)==0)
                    {
                        System.out.println(x[i].divide(y[i]));
                    }
                    else
                    {
                        System.out.println(x[i]+"/"+y[i]);
                    }
                }
            }
            else
            {
                System.out.println("No solution.");
            }
            System.out.println();
        }
    }
}

Simple Addition expression

题意:给出数n,在区间[0,n]中取值i,使得 (i) + (i+1) + (i+2), i>=0间的计算不会产生进位

统计在小于n的情况下,有多少个i符合i+i+1+i+2没有进位
首先因为没有进位,那么能够确定除了个位之外所有是0~3
而个位因为加了3,那么个位仅仅能是0~2

然后又研究了好一会才知道什么解,个位数不能超过2,其他位数不超过3即可:即个位最大为3,其他位最大为4.把这个数当做字符串就好解决了,从这个字符串的第一位开始判断就可以了……然后计算这些排列数就行了。如果为个数,就直接加上,如果有其他位数,那先判断第一位,如果大于3就可以直接用相乘,如果小于3的话,那这位数之前的可以直接相乘,这位数的情况就往下位数继续判断……这样依次判断到最后个位数就行了……把这些结果相加就得到结果了。

#include<bits/stdc++.h>

using namespace std;
char a[100];
typedef long long ll;
ll sum,c;
int main()
{
    while (~scanf("%s",a))
    {
        sum=0;
        int len=strlen(a);
        for (int i=0; i<len; i++)
        {
            c=a[i]-'0';
            if (i==len-1)
            {
                if (c<3)
                {
                    sum+=c;
                }
                else
                {
                    sum+=3;
                }
                break;
            }
            if (c<4)
            {
                sum+=c*pow(4,len-i-2)*3;
            }
            else
            {
                sum+=pow(4,len-i-1)*3;
                break;
            }
        }
        printf("%lld
",sum);
    }
}

Degree Sequence of Graph G

#include<bits/stdc++.h>

using namespace std;
priority_queue<int>q;
int a[100000],n,x,f;
int main(){
    int T;
    scanf("%d",&T);
    while (T--){
        f=0;
        while (!q.empty()){
            q.pop();
        }
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            scanf("%d",&x);
            if (x) q.push(x);
        }
        while (!q.empty()){
            x=q.top();
            q.pop();
            if (x>q.size()){
                f=1;
                break;
            }
            for (int i=1;i<=x;i++){
                a[i]=q.top()-1;
                q.pop();
            }
            for (int i=1;i<=x;i++){
                if (a[i]){
                    q.push(a[i]);
                }
            }
        }
        if (f){
            printf("no
");
        }else{
            printf("yes
");
        }
    }
}

Navy maneuvers

#include<bits/stdc++.h>

using namespace std;
const int maxn=10010;
int f[10010][2],in[maxn],w[maxn],m,n,ff;
vector<int>E[maxn];
int dfs(int cur,int turn){
    if (f[cur][turn&1]!=-1){
        return f[cur][turn&1];
    }
    if (E[cur].size()==0){
        return f[cur][turn&1]=w[cur];
    }
    f[cur][turn&1]=0;
    int len=E[cur].size(),mn=0x3f3f3f3f,mx=-0x3f3f3f3f;
    for (int i=0;i<len;i++){
        int to = E[cur][i];
        if (turn&1){
            mx=max(mx,dfs(to,turn+1));
        }else{
        mn=min(mn,dfs(to,turn+1));
        }
    }
    if (turn&1){
        return f[cur][turn&1]=w[cur]+mx;
    }else{
        return f[cur][turn&1]=w[cur]+mn;
    }
}
int main()
{
    while (~scanf("%d%d%d",&n,&m,&ff))
    {
        memset(f,-1,sizeof (f));
        for (int i=1; i<=n; i++)
        {
            in[i]=0;
            E[i].clear();
        }
        int ans=0;
        for (int i=1; i<=n; i++)
        {
            scanf("%d",&w[i]);
        }
        for (int i=1,u,v; i<=m; i++)
        {
            scanf("%d%d",&u,&v);
            E[u].push_back(v);
            in[v]++;
        }
        for (int i=1; i<=n; i++)
        {
            if (!in[i])
            {
                ans=max(ans,dfs(i,1));
            }
        }
        if (ans>=ff)
        {
            puts("Victory");
        }
        else
        {
            puts("Glory");
        }
    }
    return 0;
}

Mining Station on the Sea

给你n个船和n个港口,m个采矿点,k条矿点之间的边,p条港口和矿井的边。问n条船与n个港口一一匹配的最小路程。将路程转化为费用,用最小费用流模型求解。
设矿点的编号为1 ~ m,港口的编号m + 1 ~ m + n
对所有的船 i 和起点建边(s,i, 1, 0);
对所有的港口 x 和终点建边(x + m, t, 1, 0);
对有路的矿点 u 和矿点 v建边(u,v,oo,w),(v,u,oo,w),因为路可以重复走,所以容量设为oo;
最后对有路的矿点 u 和港口 v 建边(v,u + m,1,w)。

建图如下:

①建立源点S,将其连入各个船所在的点,权值设定为1,费用设定为0,表示只有一个船.

②建立汇点T,将各个港口连入汇点T,权值设定为1,费用设定为0,表示只能停一个船.

③将m条无向边直接建立起来,权值设定为其距离,费用设定为INF。表示可以走无数次。

④将p条有向边直接建立起来,将点连入港口,权值设定为其距离,费用设定为1。

#include <bits/stdc++.h>

using namespace std;
const int maxm=2000000;
const int maxn=330;
const int inf=0x3f3f3f3f;
typedef pair<int,int> PI;
struct MCFC {
    struct edge {
        int to, next, cap, flow, cost;
    } e[maxm];
    int head[maxn], tol;
    int pre[maxn], dis[maxn];
    bool vis[maxn];
    int N;

    void init(int n) {
        N = n;
        tol = 1;
        memset(head, 0, sizeof(head));
    }

    void addedge(int u, int v, int cap, int cost) {
        tol++;
        e[tol].to = v;
        e[tol].cap = cap;
        e[tol].cost = cost;
        e[tol].flow = 0;
        e[tol].next = head[u];
        head[u] = tol;
        tol++;
        e[tol].to = u;
        e[tol].cap = 0;
        e[tol].flow = 0;
        e[tol].cost = -cost;
        e[tol].next = head[v];
        head[v] = tol;
    }

    bool spfa(int s, int t) {
        queue<int> q;
        for (int i = 0; i <= N; i++) {
            dis[i] = inf;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push(s);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            vis[u] = false;
            for (int i = head[u]; i; i = e[i].next) {
                int v = e[i].to;
                if (e[i].cap > e[i].flow && dis[v] >dis[u] + e[i].cost) {
                    dis[v] = dis[u] + e[i].cost;
                    pre[v] = i;
                    if (!vis[v]) {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        if (pre[t] == -1) return false;
        else return true;
    }

    int cost = 0;

    PI mcmf(int s, int t) {
        int flow = 0;
        cost = 0;
        while (spfa(s, t)) {
            int minn = inf;
            for (int i = pre[t]; i != -1; i = pre[e[i ^ 1].to]) {
                if (minn > e[i].cap - e[i].flow) {
                    minn = e[i].cap - e[i].flow;
                }
            }
            for (int i = pre[t]; i != -1; i = pre[e[i ^ 1].to]) {
                e[i].flow += minn;
                e[i ^ 1].flow -= minn;
                cost += e[i].cost * minn;
            }
            flow += minn;
        }
        return make_pair(cost,flow);
    }

} G;

int main(){
    int n,m,k,p,T,S,pos,u,v,w;
    while (~scanf("%d%d%d%d",&n,&m,&k,&p)){
        T=n+m+1;
        S=0;
        G.init(T);
        for (int i=1;i<=n;i++){
            scanf("%d",&pos);
            G.addedge(S,pos,1,0);
        }
        for (int i=1;i<=n;i++){
            G.addedge(m+i,T,1,0);
        }
        for (int i=1;i<=k;i++){
            scanf("%d%d%d",&u,&v,&w);
            G.addedge(u,v,inf,w);
            G.addedge(v,u,inf,w);
        }
        for (int i=1;i<=p;i++){
            scanf("%d%d%d",&u,&v,&w);
            G.addedge(v,u+m,1,w);
        }
        printf("%d
",G.mcmf(S,T).first);
    }
}
#include <bits/stdc++.h>

using namespace std;
const int maxm=900000;
const int maxn=330;
const int inf=0x3f3f3f3f;
typedef pair<int,int> PI;

struct Min_Cost_Max_Flow{
    struct edge{
        int to,cap,cost,rev;
        edge(){};
        edge(int _to,int _cap,int _cost,int _rev):to(_to),cap(_cap),cost(_cost),rev(_rev){};
    };
    vector<edge>E[maxm];
    int h[maxn],n,d[maxn],preV[maxn],preE[maxn];
    void init(int n){
        this->n=n;
        for (int i=0;i<=n;i++){
            E[i].clear();
            h[i]=0;
        }
    }
    void add(int from,int to,int cap,int cost){
        E[from].push_back(edge(to,cap,cost,E[to].size()));
        E[to].push_back(edge(from,0,-cost,E[from].size()-1));
    }

    PI dijkstra(int s,int t,int f){
        int cost=0,flow=0;
        for (int i=0;i<=n;i++){
            h[i]=0;
        }
        while (f){
            priority_queue<PI,vector<PI>,greater<PI> >q;
            for (int i=0;i<=n;i++){
                d[i]=inf;
            }
            d[s]=0;
            q.push(make_pair(0,s));
            while (!q.empty()){
                PI now=q.top();
                q.pop();
                int v=now.second;
                if (d[v]<now.first){
                    continue;
                }
                for (int i=0;i<E[v].size();i++){
                    edge &e=E[v][i];
                    if (e.cap>0&&d[e.to]>d[v]+e.cost+h[v]-h[e.to]){
                        d[e.to]=d[v]+e.cost+h[v]-h[e.to];
                        preV[e.to]=v;
                        preE[e.to]=i;
                        q.push(make_pair(d[e.to],e.to));
                    }
                }
            }
            if (d[t]==inf)break;
            for (int i=0;i<=n;i++){
                h[i]+=d[i];
            }
            int d=f;
            for (int i=t;i!=s;i=preV[i]){
                d=min(d,E[preV[i]][preE[i]].cap);
            }
            f-=d;
            flow+=d;
            cost+=d*h[t];
            for (int i=t;i!=s;i=preV[i]){
                    edge &e=E[preV[i]][preE[i]];
                    e.cap-=d;
                    E[i][e.rev].cap+=d;
            }
        }
        return make_pair(flow,cost);
    }
}G;

int main(){
    int n,m,k,p,T,S,pos,u,v,w;
    while (~scanf("%d%d%d%d",&n,&m,&k,&p)){
        T=n+m+1;
        S=0;
        G.init(T);
        for (int i=1;i<=n;i++){
            scanf("%d",&pos);
            G.add(S,pos,1,0);
        }
        for (int i=1;i<=n;i++){
            G.add(m+i,T,1,0);
        }
        for (int i=1;i<=k;i++){
            scanf("%d%d%d",&u,&v,&w);
            G.add(u,v,inf,w);
            G.add(v,u,inf,w);
        }
        for (int i=1;i<=p;i++){
            scanf("%d%d%d",&u,&v,&w);
            G.add(v,u+m,1,w);
        }
        printf("%d
",G.dijkstra(S,T,inf).second);
    }
}

Carrying Out A Task

简述一下题意:

20*20的地图上,一个起点S,一个终点E,障碍物#,漩涡*

一艘船从起点出发,携带充足的A类油和X升B类油。

沿上下左右四个方向行驶,不能在障碍物的格子行驶;可以进入漩涡,但每次进入船会受伤。没走过一个格子都要消耗一升A类油。

每个回合有两个操作:

1.普通航行一格

2.加速一次消耗Y升B类油,有两种加速方法,加速规则:

    a.在某一个方向连续航行d步,d步之内不能有障碍物、漩涡,不能驶出地图

    b.当下一步要驶入漩涡时,必须加速、进入漩涡后加速效果消失

询问船是否可以到达终点,输出最少多少个回合到达,前提——船受到的伤害最小(进入漩涡次数最少),其次消耗A类油最少(走过的格子数最少),再次回合数最少。

简述方法:限制条件的SPFA。用优先队列,不断更新符合要求的最短路径。

                        利用num[横坐标][纵坐标][受伤次数] 来记录所剩余的最大加速次数,如果后来者所存有的加速次数比先到者的多,就再走一遍。

                        利用优先队列,按照 1. 受伤次数最少  、 2. 耗A量最少   、3. 步数最少 ,按顺序进行优先级排序,依次最少的先出队列

                        这里有两个比较好的剪枝:

                                          1. 先搜索一遍,能否到达终点 

                                          2.  num[x][y][当前受伤次数-1]的位置如果已经走过,就不再走,既然少受伤一次能都路过,现在就不必再走了

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
 
using namespace std;
 
const int maxn=22;
const int fy[]={0,0,-1,1};
const int fx[]={1,-1,0,0};
 
struct Point{ // damage ,B-cost,A-cost 
	int x,y,step,dmg,bcst,acst;
	Point(){}
	Point(int tx,int ty,int ts,int td,int ta,int tb){
		x=tx,y=ty,step=ts,dmg=td,acst=ta,bcst=tb;
	}
	bool friend operator<(Point p,Point q){
		if(p.dmg!=q.dmg) return p.dmg>q.dmg;
		if(p.acst!=q.acst) return p.acst>q.acst;
		return p.step>q.step;
	}
}; 
struct Cdnt{ // Coordinate 
	int x,y,cst;
	Cdnt(){};
	Cdnt(int tx,int ty,int tc){x=tx,y=ty,cst=tc;} 
	bool friend operator<(Cdnt p,Cdnt q){
		return p.cst>q.cst;
	}
};
char mp[maxn][maxn];
int n,m,sx,sy,dis; 
 
int CBA(){ // E can be arrived ? Return the number of damage.
	int k;
	bool vis[maxn][maxn];
	Cdnt now,next;
	priority_queue<Cdnt>q;
	memset(vis,false,sizeof(vis));
	q.push(Cdnt(sx,sy,0));
	vis[sx][sy]=true;
	while(!q.empty()){
		now=q.top();
		q.pop();
		if(mp[now.x][now.y]=='E') return now.cst;
		for(k=0;k<4;k++){
			next.x=now.x+fx[k];
			next.y=now.y+fy[k];
			if(next.x<0 || next.x>=n || next.y<0 || next.y>=m) continue;
			if(vis[next.x][next.y] || mp[next.x][next.y]=='#') continue;
			if(mp[next.x][next.y]=='*') next.cst=now.cst+1;
			else next.cst=now.cst;
			vis[next.x][next.y]=true; 
			q.push(next);
		} 
	}
	return -1;
}
 
priority_queue<Point>que;
 
short num[maxn][maxn][maxn*maxn]; //  [x][y][number of undercurrent] for accelerate
 
void init_(int res){
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			for(int k=0;k<=res;k++)
				num[i][j][k]=-1;
	while(!que.empty()) que.pop();
}
 
int bfs(int v){ // v  ->  The number of total acceleration.
	int res,k,z;
	Point now,next;
	res=CBA();
	if(res==-1 || res>v) return -1;
	init_(res+1);
	que.push(Point(sx,sy,0,1,0,v));
	num[sx][sy][1]=v;
	while(!que.empty()){
		now=que.top();
		que.pop();
//		cout<<now.x<<" "<<now.y<<endl;
		if(mp[now.x][now.y]=='E') return now.step;
		for(k=0;k<4;k++){
			if(now.bcst>res-now.dmg){
				next=now;
				for(z=0;z<dis;z++){
					next.x+=fx[k];
					next.y+=fy[k];
					if(next.x>=n || next.y>=m || next.x<0 || next.y<0) break;
					if(mp[next.x][next.y]=='#' || mp[next.x][next.y]=='*') break;
				}
				if(z==dis){
					next.step++;
					next.bcst--;
					next.acst+=dis;
					if(num[next.x][next.y][next.dmg]<next.bcst && num[next.x][next.y][next.dmg-1]==-1){
						num[next.x][next.y][next.dmg]=next.bcst;
						que.push(next);
					}
				}
			}
			next=now;
			next.x+=fx[k];
			next.y+=fy[k];
			next.step++;
			next.acst++;
			if(next.x>=n || next.y>=m || next.x<0 || next.y<0) continue;
			if(mp[next.x][next.y]=='#') continue;
			if(mp[next.x][next.y]=='*'){
				if(next.bcst>0) next.bcst--,next.dmg++;
				else continue;
			}
			if(num[next.x][next.y][next.dmg]<next.bcst && num[next.x][next.y][next.dmg-1]==-1){
				num[next.x][next.y][next.dmg]=next.bcst;
				que.push(next);
			}
		}
	}
	return -1;
}
 
int main(){
	int t,i,j,res;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d
",&n,&m);
		for(i=0;i<n;i++){
			gets(mp[i]);
			for(j=0;j<m;j++)
				if(mp[i][j]=='S')
		  			sx=i,sy=j;
		}
		scanf("%d",&dis);
		scanf("%d%d",&i,&j);
		res=bfs(i/j);
		if(res==-1) puts("can not reach!");
		else printf("%d
",res);
	}	
	return 0;
}

K-dimension number

题意:定义K-维数M:如果M的因数个数为K,则M为K-维数。题目的要求是求第N个K-维数。N<10000,Kmax<=100,Kmax是K的最大质因数。如果K是一个kk-维数,则kk<=3。

分析:
如果M = x1^p1 * x2^p2 * ... * xn^pn (x1,x2...xn均为质数),则 K = (p1+1)*(p2+1)*...*(pn+1). 


这道题重要的条件是:如果K是一个kk-维数,则kk<=3。根据这个条件可以确定K的范围。kk的取值只有三种1,2,3。如果kk=1,则K=1;如果kk=2,K=p(p为质数);如果kk=3,K=p^2(p为质数)。 
  
分情况讨论,如果K = 1,则原数M只可能为1,因为只有1的因数个数为1。如果K = p(p为质数),则原数M = x^(p-1)(x也为质数),找到第n个数只需遍历一下质数表就可以了。如果K=p^2(p为质数),则原数M = x1^(p-1)*x2^(p-1) = (x1*x2)^(p-1) (x1,x2均为质数且不等),或者 M = x1^(K-1) (x1为质数)。这种情况下找到第n个K-维数就比较复杂了,首先要找到前10000个两个不等质数之积,在对质数表和两个质数积表进行扫描,找到第n个值。 

本题目是一个非常好的数学题,根据上面的三种情况主要有如下结论:
1.当k=1时,结果直接为1
2.当k=p时,结果为prime[n]^(k-1),这里的prime[n]为从2开始的第n个素数
3.当k=p^2时,结果为p^(k-1)和(p1*p2)^(p-1)之中的第n个数(这里p1,p2为任意素数)

当然知道结论是不够的,本题需要解决几个难点
1.大数,这里用java解决简单了许多
2.上述的情况三时,到底如何知道第n个数是什么呢?
3.不断的大数运算是否会超时???这里算阶乘的时候我们全部用log算!这样节约了很多时间空间!!!

为了解决第二个问题直观的想法就是暴力,但是绝对的超时,这个也是学到的最巧妙的一个思路。
首先我们在最最开始的时候需要得到一个至少长度为10000的素数表(情况二就会用到了),我们在考虑情况三时往往想p1,p2值是多少然后乘起来比较大小,那么换一种思路,假如我们知道一个数a,且知道该数的一个素数约数b,那么判断a/b是否为素数,如果是说明满足了条件。

import java.util.*;
import java.math.*;
import java.io.*;

public class Main{
	public static void main(String[] args){
		final int N=105050;
		int pnum=0;
		int []prime = new int [10050];
		int []pd = new int [N+5];
		int cnt=0;
		int []pl= new int [10050];
		int n,k;
		for (int i=1;i<=N;i++){
			pd[i]=0;
		}
		for (int i=2;i<=N;i++){
			if (pd[i]==0){
				prime[++pnum]=pd[i]=i;
			}
			for (int j=1;j<=pnum&&i*prime[j]<=N;j++){
				pd[i*prime[j]]=prime[j];
				if (i%prime[j]==0){
					break;
				}
			}
		}
		for (int i=6;i<=41200;i++){
			int x=i/pd[i];
			if (pd[i]!=x&&x==pd[x]){
				pl[++cnt]=i;
			}
		}
		
		Scanner cin = new Scanner(System.in);
		while (cin.hasNext()){
			n=cin.nextInt();
			k=cin.nextInt();
			int p1=0,p2=0;
			for (int i=1;i<=pnum;i++){
				if (k%prime[i]==0){
					p1=prime[i];
					p2=k/prime[i];
				}
			}
			if (k==1){
				System.out.println(1);
				continue;
			}
			if (p2==1){
				BigInteger temp=BigInteger.valueOf(prime[n]);
				temp=temp.pow(k-1);
				System.out.println(temp);
				continue;
			}
			if (p1==p2){
				int i=1,j=1;
				while (true){
					double x=(p1*p1-1)*Math.log10(prime[i]),y=(p1-1)*Math.log10(pl[j]);
					BigInteger sum1=BigInteger.valueOf(prime[i]).pow(p1*p1-1),sum2=BigInteger.valueOf(pl[j]).pow(p1-1);
					if (x<=y){
						i++;
						if (i+j-2==n){
							System.out.println(sum1);
							break;
						}
					}else{
						j++;
						if (i+j-2==n){
							System.out.println(sum2);
							break;
						}
					}
				}
			}
		}
	}
}

  

原文地址:https://www.cnblogs.com/Accpted/p/11310855.html