PTA甲级(Advanced Level)个人题解(持续更新中)

1001. A+B Format

输出A+B,从低位到高位每三个数位用半角逗号分隔;直接模拟即可,可转换成字符串,也可以不断对10取模

    public static void main(String[] args) throws Exception {
        int a=in.readInt();
        int b=in.readInt();
        int ans=a+b,k=0;
        Deque<Character> stack=new ArrayDeque<>();
        String s=String.valueOf(abs(ans));
        for(int i=s.length()-1;i>=0;i--){
            stack.push(s.charAt(i));
            k++;
            if(k%3==0) stack.push(',');
        }
        if(stack.peek()==',') stack.pop();
        if(ans<0) out.print('-');
        while(!stack.isEmpty()){
            out.print(stack.pop());
        }
        out.close();
    }

1002.A+B for Polynomials

多项式加法,输出运算后有多少项和每一项的指数以及系数,注意按照样例依指数从大到小输出

,同时注意删除系数为0的项,可用map实现。

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        int exp=0;
        double coe=0;
        TreeMap<Integer,Double> map=new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        while(n-->0){
            exp=in.readInt();
            coe=in.readDouble();
            map.merge(exp,coe,Double::sum);
        }
        m=in.readInt();
        while(m-->0){
            exp=in.readInt();
            coe=in.readDouble();
            map.merge(exp,coe,Double::sum);
            if(map.get(exp)==0) map.remove(exp);
        }
        out.print(map.size());
        for(int key:map.keySet()){
            out.print(" "+key+" "+new DecimalFormat(".0").format(map.get(key)));
        }
        out.close();
    }

1003.Emergency

给定一张无向图以及数点间的边权和各点点权,求给定两点间最短路径数量以及最短路径上的点权和的最大值

最短路Dijkstra,由于数据很小,朴素版和堆优化版均可以通过。难点在于如何求出最短路径数量。令cnt[u] 表示在当前得到u的最短路距离的路径条数,v为u的下一个节点。若此时到v的最短距离小于已记录最短距离,更新最短距离,且最短路径数一起更新,即cnt[v]=cnt[u];若此时最短距离等于已记录最短距离,则说明有新的最短路径,即cnt[v]+=cnt[u];注意初始化起点cnt为1.

    static class edge{
        int u,v,w;

        public edge(int u, int v, int w) {
            this.u = u;
            this.v = v;
            this.w = w;
        }
    }
    static Vector<edge> e;
    static Vector<Integer>[] h;
    static int[] a,d,sum,cnt;
    static boolean[] vis;
    static void add(int u,int v,int w){
        e.add(new edge(u,v,w));
        h[u].add(e.size()-1);
    }
    static void Init(int n){
        h=new Vector[n+10];
        for(int i=0;i< h.length;i++) h[i]=new Vector<>();
        e=new Vector<>();
        a=new int[n+10];
        d=new int[n+10];
        vis=new boolean[n+10];
        sum=new int[n+10];
        cnt=new int[n+10];
    }
    static void Dijkstra(int s,int end){
        Arrays.fill(d,0x3f3f3f3f);
        Arrays.fill(vis,false);
        PriorityQueue<int[]> p=new PriorityQueue<>((a,b)->(a[0]-b[0]));
        d[s]=0;
        cnt[s]=1;
        p.offer(new int[]{0,s});
        while(!p.isEmpty()){
            int[] t=p.poll();
            int u=t[1];
            if(vis[u]) continue;
            vis[u]=true;
            for(int ed:h[u]){
                int v=e.get(ed).v;
                int w=e.get(ed).w;
                if(d[u]+w<d[v]){
                    d[v]=d[u]+w;
                    p.offer(new int[]{d[v],v});
                    cnt[v]=cnt[u];
                    sum[v]=sum[u]+a[v];
                }
                else if(d[u]+w==d[v]){
                    cnt[v]+=cnt[u];
                    sum[v]=max(sum[v],sum[u]+a[v]);
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        m=in.readInt();
        int s=in.readInt();
        int end=in.readInt();
        Init(n);
        for(int i=0;i<n;i++) a[i]=in.readInt();
        for(int i=0;i<m;i++){
            u=in.readInt();
            v=in.readInt();
            w=in.readInt();
            add(u,v,w);
            add(v,u,w);
        }
        sum[s]=a[s];
        Dijkstra(s,end);
        out.print(cnt[end]+" "+sum[end]);
        out.close();
    }
}

1004.Counting Leaves

给定一个森林的节点个数,以及各点的儿子,求各层次的叶子个数

可记录各层次的点,然后检查其是否有儿子

    static void Init(int n){
        h=new Vector[n+10];
        dep=new Vector[n+10];
        d=new int[n+10];
        for(int i=0;i<h.length;i++) h[i]=new Vector<>();
        for(int i=0;i<h.length;i++) dep[i]=new Vector<>();
    }
    static Vector<Integer>[] h,dep;
    static int[] d;
    static int maxDep=1;
    static void getDep(int u){
        for(int i=0;i<h[u].size();i++){
            int v=h[u].get(i);
            d[v]=d[u]+1;
            maxDep=max(maxDep,d[v]);
            dep[d[v]].add(v);
            getDep(v);
        }
    }

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        m=in.readInt();
        Init(n);
        while(m-->0){
            int idx=in.readInt();
            int cnt=in.readInt();
            while(cnt-->0){
                int kid=in.readInt();
                h[idx].add(kid);
            }
        }
        d[1]=1;
        dep[1].add(1);
        getDep(1);
        for(int i=1;i<=maxDep;i++){
            int cnt=0;
            for(int j=0;j<dep[i].size();j++){
                u=dep[i].get(j);
                if(h[u].size()==0) cnt++;
            }
            if(i==1) out.print(cnt);
            else out.print(" "+cnt);
        }
        out.close();
    }
}

1005.Spell It Right

给出一数,对其所有数位上的数字求和,然会从高位到低位输出结果各数位数字的英文。

字符串读入,哈希表读取即可

    public static void main(String[] args) throws Exception {
        HashMap<Character,String> map=new HashMap<>(){{
            put('0',"zero");put('1',"one");put('2',"two");
            put('3',"three");put('4',"four");put('5',"five");
            put('6',"six");put('7',"seven");put('8',"eight");
            put('9',"nine");
        }};
        String s=in.readStringLine();
        int sum=0;
        for(int i=0;i<s.length();i++){
            sum+=(s.charAt(i)-'0');
        }
        s=String.valueOf(sum);
        for(int i=0;i<s.length();i++){
            char ch=s.charAt(i);
            if(i==0) out.print(map.get(ch));
            else out.print(" "+map.get(ch));
        }
        out.close();
    }

1006.Sign In and Sign Out

给定n个人的ID_number,到达和离开的时间,求最先到达和最后离开的人的ID_number。

字符串比较,自定义排序即可

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        String[][] str=new String[n][];
        for(int i=0;i<n;i++) str[i]=in.readStringLine().split(" ");
        String[][] copy=str.clone();
        Arrays.sort(str, new Comparator<String[]>() {
            @Override
            public int compare(String[] o1, String[] o2) {
                return o1[1].compareTo(o2[1]);
            }
        });
        Arrays.sort(copy, new Comparator<String[]>() {
            @Override
            public int compare(String[] o1, String[] o2) {
                return o2[2].compareTo(o1[2]);
            }
        });
        out.print(str[0][0]+" "+copy[0][0]);
        out.close();
    }

1007.Maximum Subsequence Sum

给出n个数,输出最大子段和及左右边界;若有多个答案,输出最小下标的左右边界

最大子段和板子题,只需另外记录左右边界即可

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        int[] a=new int[n+1];
        int f=0;
        long ans=0,res=0,l=0,r=0,ansl=0,ansr=0;
        for(int i=1;i<=n;i++){
            a[i]=in.readInt();
            if(a[i]>=0) f=1;
            if(res>0) {
                res+=a[i];
            }
            else{
                l=a[i];
                res=a[i];
            }
            if(res>ans){
                ans=res;
                r=a[i];
                ansl=l;
                ansr=r;
            }
        }
        if(f==0) out.print(0+" "+a[1]+" "+a[n]);
        else out.print(ans+" "+ansl+" "+ansr);
        out.close();
    }

1008.Elevator

简单模拟,注意上次与本次是同一楼层需要加5秒

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        int pre=0,cur=0,ans=0;
        for(int i=1;i<=n;i++){
            cur=in.readInt();
            if(cur>pre) ans+=(cur-pre)*6+5;
            else if(cur<pre) ans+=(pre-cur)*4+5;
            else ans+=5;
            pre=cur;
        }
        out.print(ans);
        out.close();
    }

1009.Product of Polynomials

模拟,多项式乘法,同1002,注意删除系数为0的项

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        int exp=0;
        double coe=0;
        TreeMap<Integer,Double> map=new TreeMap<>((o1,o2)->(o2-o1));
        int[] a=new int[n];
        double[] b=new double[n];
        for(int i=0;i<n;i++){
            a[i]=in.readInt();
            b[i]=in.readDouble();
        }
        m=in.readInt();
        while(m-->0){
            exp=in.readInt();
            coe=in.readDouble();
            for(int i=0;i<n;i++){
                map.merge(exp+a[i],coe*b[i],Double::sum);
            }
        }
        Vector<Integer> v=new Vector<>();
        for(int key:map.keySet()){
            v.add(key);
        }
        for(int key:v){
            if(map.get(key)==0) map.remove(key);
        }
        out.print(map.size());
        for(int key:map.keySet()){
            out.print(" "+key+" "+new DecimalFormat(".0").format(map.get(key)));
        }
        out.close();
    }

1010.Radix

模拟,二分

k进制下,取模最大数字为k-1,所以目的串的最大数字加1即为操作串的最小进制,最大进制为目的串本身。但由于目的串在转换成十进制时可能非常大造成溢出变成负数,故最大进制为max(目的串本身,最小进制);找到进制范围后,二分即可。需要注意二分过程中若返回负数,代表此时选择的进制仍然较大,需要减小右边界。

    static int getmaxdigit(String s){
        int ans=0;
        char ch;
        for(int i=0;i<s.length();i++){
            ch=s.charAt(i);
            if(ch>'9') ans=max(ans,ch-'a'+10);
            else ans=max(ans,ch-'0');
        }
        return ans;
    }
    static long f(String s,long radix){
        long ans=0;
        long p=1,x;
        char ch;
        for(int i=s.length()-1;i>=0;i--){
            ch=s.charAt(i);
            if(ch>'9') x=ch-'a'+10;
            else x=ch-'0';
            ans+=x*p;
            p*=radix;
            if(ans<0) return -1;//溢出
        }
        return ans;
    }


    public static void main(String[] args) throws Exception {
        String a=in.readString();
        String b=in.readString();
        int tag=in.readInt();
        int radix=in.readInt();
        if(tag==2){
            String s=b;
            b=a;
            a=s;
        }
        long des=f(a,radix);
        long l=getmaxdigit(b)+1;//最小进制为最大数位+1
        long r=max(des,l);//最大进制为目的数本身
        while(l<=r){
            long mid=l+r>>1;
            long t=f(b,mid);
            if(t==-1||t>des){//若溢出,则当前进制太大
                r=mid-1;
            }
            else l=mid+1;
        }
        if(f(b,l-1)==des) out.print(l-1);
        else out.print("Impossible");
        out.close();
    }

1011.World Cup Betting

简单模拟,找到每组的最大值即可

    public static void main(String[] args) throws Exception {
        double a,b,c,max=0,ans=1;
        char[] res=new char[3];
        for(int i=0;i<3;i++){
            a=in.readDouble();
            b=in.readDouble();
            c=in.readDouble();
            max=max(max(a,b),c);
            ans*=max;
            if(max==a) res[i]='W';
            else if(max==b) res[i]='T';
            else res[i]='L';
        }
        ans=(ans*0.65-1)*2;
        out.print(res[0]+" "+res[1]+" "+res[2]+" "+new DecimalFormat(".00").format(ans));
        out.close();
    }

1012.The Best Rank

排序,二分

找出每个人在四个科目中的最优名次,输出即可

    static int binarySearch(Integer[] a,int x){
        int n=a.length-1;
        if(x==a[0]) return 0;
        int l=0,r=n;
        while(l<=r){
            int mid=l+r>>1;
            if(a[mid]<=x) r=mid-1;
            else l=mid+1;
        }
        return l;
    }

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        int q=in.readInt();
        HashMap<String,int[]> map=new HashMap<>();
        Integer[] C=new Integer[n];
        Integer[] M=new Integer[n];
        Integer[] E=new Integer[n];
        Integer[] A=new Integer[n];
        for(int i=0;i<n;i++){
            String s=in.readString();
            C[i]=in.readInt();
            M[i]=in.readInt();
            E[i]=in.readInt();
            A[i]=(C[i]+M[i]+E[i])/3;
            map.put(s,new int[]{C[i],M[i],E[i],A[i]});
        }
        Arrays.sort(C,(i,j)->(j-i));
        Arrays.sort(M,(i,j)->(j-i));
        Arrays.sort(E,(i,j)->(j-i));
        Arrays.sort(A,(i,j)->(j-i));
        int c,m,e,a;
        while(q-->0){
            String s=in.readString();
            if(!map.containsKey(s)) out.printLine("N/A");
            else{
                int[] t=map.get(s);
                c=t[0];m=t[1];e=t[2];a=t[3];
                int idx1=binarySearch(C,c);
                int idx2=binarySearch(M,m);
                int idx3=binarySearch(E,e);
                int idx4=binarySearch(A,a);
                int ans=min(min(min(idx1,idx2),idx3),idx4);
                ans++;
                if(ans==idx4+1) out.printLine(ans+" A");
                else if(ans==idx1+1) out.printLine(ans+" C");
                else if(ans==idx2+1) out.printLine(ans+" M");
                else out.printLine(ans+" E");
            }
        }
        out.close();
    }

1013.Battle Over Cities

给出一张无向图,求在给定删除某点后需要添加多少条边使整图连通。问题可转换为求出有多少连通块。

1.并查集

    static class Edge{
        int u,v;
        public Edge(int u, int v) {
            this.u = u;
            this.v = v;
        }
    }
    static Vector<Edge> e;
    static int[] fa;
    static void Init(int n){
        e=new Vector<>();
        fa=new int[n+1];
    }
    static int find(int x){
        if(x!=fa[x]) fa[x]=find(fa[x]);
        return fa[x];
    }
    static void reFill(){
        for(int i=1;i<=n;i++) fa[i]=i;
    }

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        m=in.readInt();
        int k=in.readInt();
        Init(n);
        while(m-->0){
            u=in.readInt();
            v=in.readInt();
            e.add(new Edge(u,v));
        }
        while(k-->0){
            reFill();
            HashSet<Integer> set=new HashSet<>();
            int q=in.readInt();
            for(Edge edge:e){
                u=edge.u;
                v=edge.v;
                if(u==q||v==q) continue;
                int fu=find(u);
                int fv=find(v);
                if(fv!=fu) fa[fu]=fv;
            }
            for(int i=1;i<=n;i++){
                if(i==q) continue;
                set.add(find(i));
            }
            out.printLine(set.size()-1);
        }
        out.close();
    }

2.建图跑dfs

    static class Graph{
        int n,m,cnt=0;
        Vector<Integer>[] h;
        boolean[] vis;

        public Graph(int n, int m) {
            this.n = n;
            this.m = m;
            h=new Vector[n+1];
            for(int i=0;i<=n;i++) h[i]=new Vector<>();
        }

        public void dfs(int v){
            for(int i=1;i<=n;i++){
                if(vis[i]||i==v) continue;
                cnt++;
                dfs(i,-1,v);
            }

        }
        public void dfs(int x,int p,int re){
            vis[x]=true;
            for(int i=0;i<h[x].size();i++){
                int v=h[x].get(i);
                if(v==p||vis[v]||v==re) continue;
                dfs(v,u,re);
            }
        }
        public void reFill(){
            cnt=0;
            vis=new boolean[n+1];
        }
    }


    public static void main(String[] args) throws Exception {
        n=in.readInt();
        m=in.readInt();
        int k=in.readInt();
        Graph G=new Graph(n,m);
        while(m-->0){
            u=in.readInt();
            v=in.readInt();
            G.h[u].add(v);
            G.h[v].add(u);
        }

        int ans=0;
        while(k-->0){
            v=in.readInt();
            G.reFill();
            G.dfs(v);
            ans=G.cnt-1;
            out.printLine(ans);
        }
        out.close();
    }

1014.Waiting in Line

队列,模拟

n个窗口用n个队列来实现,每次遍历所有窗口,弹出时间最小的元素,并添加新元素到该队列。

注意若某客人的开始时间严格小于17:00,即使完成时间超过17:00,也算完成。

    static int t = 1, n, m,u,v,w;
    static int[] a;
    static int[] pre;
    static int[] ans;
    static Queue<int[]>[] q;
    static void Init(int n,int k){
        a=new int[k+1];
        pre=new int[k+1];
        ans=new int[k+1];
        q=new Queue[n+1];
        for(int i=1;i<=n;i++) q[i]=new ArrayDeque<>();
    }
    static int[] f(){
        int idx=0;
        int t=Integer.MAX_VALUE;
        for(int i=n;i>=1;i--){
            if(!q[i].isEmpty()){
                if(pre[i]+q[i].peek()[1]<=t){
                    t=pre[i]+q[i].peek()[1];
                    idx=i;
                }
            }
        }
        if(idx==0) return new int[]{0,0,0};//是否全为空,此时结束的最小下标窗口,此时的时间
        pre[idx]+=q[idx].peek()[1];
        return new int[]{1,idx,pre[idx]};
    }

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        m=in.readInt();
        int k=in.readInt();
        int Q=in.readInt();
        int idx=0;
        Init(n,k);
        for(int i=1;i<=k;i++){
            a[i]=in.readInt();
            idx=i%n;
            if(idx==0) idx=n;
            if(q[idx].size()<m){
                q[idx].add(new int[]{i,a[i]});
            }
        }
        if(m*n<k) idx=m*n+1;
        else idx=0;
        while(true){
            int[] res=f();
            if(res[0]==0) break;
            ans[q[res[1]].poll()[0]]=res[2];
            if(idx==0) continue;
            if(idx<=k) q[res[1]].add(new int[]{idx,a[idx++]});
        }
        DecimalFormat df=new DecimalFormat("00");
        while(Q-->0){
            int x=in.readInt();
            int h=8+ans[x]/60;
            m=ans[x]%60;
            int startH=8+(ans[x]-a[x])/60;
            int startE=(ans[x]-a[x])%60;
            if(startH>=18) out.printLine("Sorry");
            else {
                String start=df.format(startH)+":"+df.format(startE);
                String end = df.format(h) + ":" + df.format(m);
                if(start.compareTo("16:59")<=0) out.printLine(end);
                else out.printLine("Sorry");
            }
        }
        out.close();
    }

1015. Reversible Primes

素数筛,进制转换

素数筛法板子题,方法很多,此处给出欧拉筛法

    static int t = 1, n, m,u,v,w,N=(int)1e5;
    static boolean[] vis=new boolean[N+10];
    static ArrayList<Integer> list=new ArrayList<>();

    static void f(){
        vis[0]=true;
        vis[1]=true;
        for(int i=2;i<=N;i++){
            if(!vis[i]) list.add(i);
            for (Integer integer : list) {
                if (i * integer > N) break;
                vis[i * integer] = true;
                if (i % integer == 0) break;
            }
        }
    }
    static int slove(int n,int radix){
        StringBuilder sb=new StringBuilder(Integer.toString(n,radix)).reverse();
        return Integer.parseInt(sb.toString(),radix);
    }

    public static void main(String[] args) throws Exception {
        f();
        while(true){
            n=in.readInt();
            if(n<0) break;
            int radix=in.readInt();
            if(vis[n]) {
                out.printLine("No");
                continue;
            }
            int ans=slove(n,radix);
            if(!vis[ans]) out.printLine("Yes");
            else out.printLine("No");
        }
        out.close();
    }

1019.General Palindromic Number

十进制转其他进制,并判断转换后是否是回文形式

    static Vector<Integer> slove(int n,int radix){
        Vector<Integer> ans=new Vector<>();
        while(n!=0){
            ans.add(n%radix);
            n/=radix;
        }
        return ans;
    }


    public static void main(String[] args) throws Exception {
        n=in.readInt();
        int radix=in.readInt();
        Vector<Integer> ans=slove(n,radix);
        int f=0;
        for(int i=0,j= ans.size()-1;i<=j;i++,j--){
            if(!Objects.equals(ans.get(i), ans.get(j))){
                f=1;
                break;
            }
        }
        if(f==0) out.printLine("Yes");
        else out.printLine("No");
        for(int i=ans.size()-1;i>=0;i--){
            if(i!=ans.size()-1) out.print(" ");
            out.print(ans.get(i));
        }
        out.close();
    }

1021.Deepest Root(C++)

      给定n点和n-1条边,判断此图是否是一个树。输出相应的连通块数量和有最长边的根节点

数据范围较小,两次dfs即可。

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include <queue>
using namespace std;
const int N = 1e4 + 10;
int a[N],pre[N];
int n, u, v;
bool vis[N];

struct edge {
	int u, v, w;
	edge(int u, int v, int w) {
		this->u = u;
		this->v = v;
		this->w = w;
	}
};
vector<edge> e;
vector<int> h[N];
void dfs_block(int u,int p) {
	if (vis[u]) return;
	vis[u] = 1;
	for (int ed : h[u]) {
		int v = e.at(ed).v;
		if (v == p) continue;
		dfs_block(v, u);
	}
}
int getBlockNumber() {
	int cnt = 0;
	for (int i = 1; i <= n; i++) {
		if (!vis[i]) {
			cnt++;
			dfs_block(i, -1);
		}
	}
	return cnt;
}

void add(int u, int v, int w) {
	e.push_back(edge(u,v,w));
	h[u].push_back(e.size()-1);
}

int dfs(int u, int p) {
	int ans = 0;
	for (int ed : h[u]) {
		int v = e.at(ed).v;
		if (v == p) continue;
		ans = max(dfs(v, u) + 1, ans);
	}
	return ans;
}

vector<int> solve() {
	vector<int> vec;
	int max = 0;
	for (int i = 1; i <= n; i++) {
		int len = dfs(i, -1);
		if (len > max) {
			max = len;
			vec.clear();
			vec.push_back(i);
		}
		else if (len == max) vec.push_back(i);
	}
	return vec;
}

int main()
{
	cin >> n;
	for (int i = 0; i < n - 1; i++) {
		cin >> u >> v;
		add(u, v, 1);
		add(v, u, 1);
	}
	int res = getBlockNumber();
	if (res != 1)
		cout << "Error: " << res << " components";
	else {
		vector<int> ans = solve();
		sort(ans.begin(),ans.end());
		for (int i : ans) {
			cout << i << endl;
		}
	}
	return 0;
}

1023.Have Fun with Numbers

判断一个数乘2后是否由原来的数位组成,数位较长,用大数

    public static void main(String[] args) throws Exception {
        String s=in.readStringLine();
        BigInteger a=new BigInteger(s);
        BigInteger ans=a.multiply(BigInteger.valueOf(2));
        HashSet<Character> set1=new HashSet<>();
        HashSet<Character> set2=new HashSet<>();
        String res=String.valueOf(ans);
        for(int i=0;i<s.length();i++) set1.add(s.charAt(i));
        for(int i=0;i<res.length();i++) set2.add(res.charAt(i));
        if(set1.equals(set2)) out.printLine("Yes");
        else out.printLine("No");
        out.printLine(res);
        out.close();
    }

1024.Palindromic Number

给定一个数和操作次数,求出该数加上自身反转后成为回文数的最小步数是否在给定次数内。

若是,输出此数和最小步数;否则输出最后操作结果

数据较长,用大数

    static boolean check(BigInteger x){
        String s=String.valueOf(x);
        for(int i=0,j=s.length()-1;i<j;i++,j--){
            if(s.charAt(i)!=s.charAt(j)) return false;
        }
        return  true;
    }
    static BigInteger reverse(BigInteger a){
        String s=String.valueOf(a);
        StringBuilder sb=new StringBuilder(s);
        return new BigInteger(sb.reverse().toString());
    }

    public static void main(String[] args) throws Exception {
        long a=in.readLong();
        int k=in.readInt();
        int cnt=0;
        BigInteger b=BigInteger.valueOf(a);
        while(cnt<k){
            if(check(b)){
                break;
            }
            cnt++;
            b=b.add(reverse(b));
        }
        out.printLine(b);
        out.printLine(cnt);
        out.close();
    }

  1027. Colors in Mars

给定三个数,输出他们各自13进制下的形式

    static String Calc(int a,HashMap<Integer,String> map){
        StringBuilder sb=new StringBuilder("");
        while(a!=0){
            int mod=a%13;
            sb.append(mod<=9?String.valueOf(mod):map.get(mod));
            a/=13;
        }
        if(sb.length()==1) sb.append("0");
        else if(sb.length()==0) sb.append("00");
        return sb.reverse().toString();
    }
    public static void main(String[] args) throws Exception {
        int a,b,c;
        a=in.readInt();
        b=in.readInt();
        c=in.readInt();
        HashMap<Integer,String> map=new HashMap<>(){{
           put(10,"A");
           put(11,"B");
           put(12,"C");
        }};
        String ans="#"+Calc(a,map)+Calc(b,map)+Calc(c,map);
        out.print(ans);
        out.close();
    }

1028.List Sorting(C++)

自定义字符串排序

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
struct Student
{
	string id;
	string name;
	int score;
};
bool cmp1(Student stu1, Student stu2)
{
	return stu1.id < stu2.id;
}
bool cmp2(Student stu1, Student stu2)
{
	return stu1.name == stu2.name ? stu1.id < stu2.id : stu1.name < stu2.name;
}
bool cmp3(Student stu1, Student stu2)
{

	return stu1.score == stu2.score ? stu1.id < stu2.id : stu1.score < stu2.score;
}
vector<Student> arr;
int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; i++)
	{
		Student stu;
		cin >> stu.id >> stu.name >> stu.score;
		arr.push_back(stu);
	}
	if (m == 1)
	{
		sort(arr.begin(), arr.end(), cmp1);
		for (int i = 0; i < n; i++)
		{
			cout << arr[i].id << " " << arr[i].name << " " << arr[i].score << endl;
		}
	}
	if (m == 2)
	{
		sort(arr.begin(), arr.end(), cmp2);
		for (int i = 0; i < n; i++)
		{
			cout << arr[i].id << " " << arr[i].name << " " << arr[i].score << endl;
		}
	}
	if (m == 3)
	{
		sort(arr.begin(), arr.end(), cmp3);
		for (int i = 0; i < n; i++)
		{
			cout << arr[i].id << " " << arr[i].name << " " << arr[i].score << endl;
		}
	}
}

1029.Median(C++)

找出给定的两个升序序列的中位数。从前往后,不断遍历即可。

#include<iostream>
#include<cstring>
using namespace std;

int main() {
	int n=0, m=0;
	cin >> n;
	int a[n + 1];
	for (int i = 1; i <= n; i++) cin >> a[i];
	cin >> m;
	int b[m + 1];
	for (int i = 1; i <= m; i++) cin >> b[i];
	int mid = n + m + 1 >> 1;
	int p = 0, i = 1, j = 1, k = 0;
	while (k != mid) {
		if (i == n + 1) {
			p = b[j]; j++; k++; continue;
		}
		if (j == m + 1) {
			p = a[i]; i++; k++; continue;
		}
		if (a[i] <= b[j]) {
			p = a[i];
			i++;
		}
		else {
			p = b[j];
			j++;
		}
		k++;
		
	}
    cout << p;
}

1030.Travel Plan

Dijkstra最短路加路径输出

    public static void main(String[] args) throws Exception {
        n=in.readInt();
        m=in.readInt();
        int s=in.readInt();
        int end=in.readInt();
        Graph g=new Graph(n,m);
        int d;
        for(int i=0;i<m;i++){
            u=in.readInt();
            v=in.readInt();
            d=in.readInt();
            w=in.readInt();
            g.add(u,v,d,w);
            g.add(v,u,d,w);
        }
        Graph.Result result=g.Dijkstra(s,end,true);
        out.printCollection(result.path);
        out.print(" "+result.d+" "+result.w);
        out.close();
    }
class Graph
{
    int n,m,INF=0x3f3f3f3f,blockNumber=0,u,v;
    Vector<edge> e=new Vector<>();
    Vector<Integer>[] h;
    public Graph(int n, int m) {
        this.n = n;
        this.m = m;
        h=new Vector[n+1];
        for(int i=0;i<=n;i++) h[i]=new Vector<>();
    }
    class edge{
        int u,v,w,d;

        public edge(int u, int v, int d) {
            this.u = u;
            this.v = v;
            this.w = d;
        }

        public edge(int u, int v, int d, int w) {
            this.u = u;
            this.v = v;
            this.w = w;
            this.d = d;
        }
    }
    void add(int u,int v,int w){
        e.add(new edge(u,v,w));
        h[u].add(e.size()-1);
        fa[v]=u;
    }
    void add(int u,int v,int w,int d){
        e.add(new edge(u,v,w,d));
        h[u].add(e.size()-1);
        fa[v]=u;
    }
    class Result{
        int d,w;
        Deque<Integer> path=new ArrayDeque<>();

        public Result(int d) {
            this.d = d;
        }
        public Result(int d, Deque<Integer> path) {
            this.d = d;
            this.path = path;
        }

    }
    Result Dijkstra(int begin,int end,boolean f){
        Result result;
        int[] dis=new int[n+1];
        int[] p=new int[n+1];
        boolean[] vis=new boolean[n+1];
        int[] val=new int[n+1];
        Arrays.fill(val,INF);
        Arrays.fill(dis,INF);
        Arrays.fill(p,-1);
        PriorityQueue<int[]> q=new PriorityQueue<>((a,b)->(a[0]-b[0]));
        q.offer(new int[]{0,begin});
        dis[begin]=0;
        val[begin]=0;
        while(!q.isEmpty()){
            int[] t=q.poll();
            int u=t[1];
            if(vis[u]) continue;
            vis[u]=true;
            for(int ed:h[u]){
                int v=e.get(ed).v;
                int d=e.get(ed).d;
                int w=e.get(ed).w;
                if(dis[u]+d<dis[v]){
                    dis[v]=dis[u]+d;
                    val[v]=val[u]+w;
                    q.offer(new int[]{dis[v],v});
                    p[v]=u;
                }
                else if(dis[u]+d==dis[v]){
                    if(val[u]+w<val[v]) p[v]=u;
                    val[v]=min(val[u]+w,val[v]);
                    q.offer(new int[]{dis[v],v});
                }
            }
        }
        if(f){
            int cur=end;
            Deque<Integer> path=new ArrayDeque<>();
            while(cur!=-1) {
                path.push(cur);
                cur = p[cur];
            }
            result=new Result(dis[end],path);
        }
        else result=new Result(dis[end]);
        result.w=val[end];
        return result;
    }

}

1031.Hello World for U

给定字符串输出其最方正的“U”字形式。

public static void main(String[] args) throws Exception {
        String s=in.readStringLine();
        n=s.length();
        if((n-2)%3==0){
            c=(n-2)/3;
        }
        else if((n-2)%3==1){
            c=(n-2)/3+1;
        }
        else c=(n-2)/3;
        int i=0,j=s.length()-1;
        for(int k=0;k<(n-c)/2-1;k++){
            for(int q=0;q<c+2;q++){
                if(q==0) out.print(s.charAt(i++));
                else if(q==c+1) out.printLine(s.charAt(j--));
                else out.print(' ');
            }
        }
        for(int k=i;k<=j;k++) out.print(s.charAt(k));
        out.close();
    }

1038.Recover the Smallest Number(C++)

给定n个数,输出这n个数能顺序组成的最小数。

自定义排序,满足任意两数的字符串形式相加小于后两数即可。

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 1e4 + 10;
string str[N];

bool cmp(string a, string b) {
	return a + b < b + a;
}

int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) cin >> str[i];
	sort(str, str + n, cmp);
	string ans = "";
	for (int i = 0; i < n; i++) ans += str[i];
	int i = 0;
	while (i < ans.size() && ans[i] == '0') i++;
	if (i == ans.size()) {
		ans = "0";
	}
	else {
		ans = ans.substr(i);
	}
	cout << ans;
	return 0;
}

1040.Longest Symmetric String

求出给定字符串的最长回文子串,马拉车经典算法

import java.util.Scanner;

public class Main {
    static Scanner in=new Scanner(System.in);
    public static int maxPalindrome(String s){
        int curCenter=0,curRight=0,maxLen=0;
        int n=s.length()*2+2;
        char[] sb=new char[n];
        int[] p=new int[n];
        sb[0]='$';
        sb[1]='#';
        int j=2;
        for(int i=0;i<s.length();i++){
            sb[j++]=s.charAt(i);
            sb[j++]='#';
        }
        for(int i=1;i<n;i++){
            p[i]=curRight>i?Math.min(p[2*curCenter-i],curRight-i):1;
            while(i-p[i]>=0&&i+p[i]<n&&sb[i-p[i]]==sb[i+p[i]]) p[i]++;
            if(curRight<i+p[i]){
                curRight=i+p[i];
                curCenter=i;
            }
            if(maxLen<p[i]){
                maxLen=p[i];
            }
        }
        return maxLen-1;
    }



    public static void main(String[] args) {
        String s=in.nextLine();
        int n=maxPalindrome(s);
        System.out.print(n);
    }
}

1041.Be Unique

找出第一个出现的不重复数字

    public static void main(String[] args) throws Exception {
        int n=in.readInt();
        int[] a=new int[n+1];
        int[] cnt=new int[N];
        for(int i=1;i<=n;i++){
            a[i]=in.readInt();
            cnt[a[i]]++;
        }
        boolean f=false;
        int ans=0;
        for(int i=1;i<=n;i++){
            if(cnt[a[i]]==1){
                f=true;
                ans=a[i];
                break;
            }
        }
        if(f) out.print(ans);
        else out.print("None");
        out.close();
    }

1042.Shuffling Machine

模拟,找出每个字符串n次变换后的位置

    public static void main(String[] args) throws Exception {
        String[] a=new String[55];
        int i=1;
        for(i=1;i<=13;i++){
            a[i]=String.valueOf("S"+i);
        }
        for(i=14;i<=26;i++){
            a[i]=String.valueOf("H"+(i-13));
        }
        for(i=27;i<=39;i++){
            a[i]=String.valueOf("C"+(i-26));
        }
        for(i=40;i<=52;i++){
            a[i]=String.valueOf("D"+(i-39));
        }
        a[53]="J1";
        a[54]="J2";
        n=in.readInt();
        int[] cnt=new int[55];
        for(i=1;i<=54;i++){
            cnt[i]=in.readInt();
        }
        String[] b=a.clone();
        int idx=0,j=1;
        for(i=1;i<=54;i++){
            j=1;
            m=cnt[i];
            while(j<=n){
                idx=m;
                m=cnt[idx];
                j++;
            }
            b[idx]=a[i];
        }
        out.printArrayBySpace(b,1,55);
        out.close();
    }

1044.Shopping in Mars(C++)

找出n个数中区间和刚好等于给定值的左右端点。若不存在,则输出区间和大于给定值的最接近的区间的端点。

双指针经典题型,不过比较的过程需要用到优先队列。注意输出格式

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include <queue>
using namespace std;
const int N = 1e5 + 10;
int a[N],pre[N];

struct node {
	int l, r, res;
	node(int l,int r,int res) {
		this->l = l;
		this->r = r;
		this->res = res;
	}
	node(const node& other) {
		this->l = other.l;
		this->r = other.r;
		this->res = other.res;
	}
	bool operator<(const node& other) const {
		return res == other.res? l>other.l : res>other.res;
	}

};

int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		pre[i] = pre[i - 1] + a[i];
	}
	int l = 1, r = 1,sum=0;
	priority_queue<node,vector<node>> q;
	while (r <= n) {
		sum += a[r];
		if (sum == m) {
			q.push(node{l, r, 0});
		}
		while (sum > m && l <= n) {
			q.push(node{l, r, pre[r] - pre[l - 1]});
			sum -= a[l++];
			if (sum == m) {
				q.push(node{l, r, 0});
			}
		}
		r++;
	}
	int minCost = q.top().res,i=1;
	while (!q.empty()) {
		node p = q.top();
		q.pop();
		if (p.res == minCost) {
			if (i == 1) cout << p.l << "-" << p.r;
			else cout << endl << p.l <<"-"<< p.r;
		}
		else break;
		i++;
	}
	return 0;
}

1045.Favorite Color Stripe

给出长度为n和m的两个数组a和b,求出按照a中元素顺序出现的顺序序列在b中的最长长度。即求最长不降子序列长度。

本质是最长上升子序列的变形题。注意没有出现的数字以及最后不要打印换行。

Java暴力写法会超时;加上快读快写可以AC

二分优化不加快读快写即可AC,感觉出题人在卡暴力做法。

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    //新元素要替换掉第一个>(=)其本身的元素
    //若没有,将其添加到末尾
    //注意c中并不是真正的上升子序列
    static Scanner in=new Scanner(System.in);

    static int find(int x,int len,int[] c){
        int l=1,r=len,mid;
        while(l<=r){
            mid=l+r>>1;
            if(x>=c[mid]) l=mid+1;
            else r=mid-1;
        }
        return l;
    }

    public static void main(String[] args) {
        int N=in.nextInt();
        int n=in.nextInt();
        int[] idx=new int[N+1];
        for(int i=1;i<=n;i++){
            int a=in.nextInt();
            idx[a]=i;
        }
        int m=in.nextInt();
        int[] b=new int[m+1];
        for(int i=1;i<=m;i++) {
            int x=in.nextInt();
            if(idx[x]!=0) b[i]=idx[x];
        }
        int len=0;
        int[] c=new int[m+1];
        for(int i=1;i<=m;i++){
            if(b[i]==0) continue;
            if(len==0){
                c[++len]=b[i];
                continue;
            }
            if(b[i]>=c[len]) c[++len]=b[i];
            else{
                int j=find(b[i],len,c);
                c[j]=b[i];
            }
        }
        System.out.print(len);
    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值