ccf 202006_4 1246

此算法模拟
https://blog.csdn.net/weixin_45919985/article/details/108101627
https://www.jianshu.com/p/efc9e984eff0
这两篇博客而写的,只用96分。
具体代码

import java.util.*;

public class Main {

    public static void main(String[] args) {
//        long stime = System.currentTimeMillis();
        Scanner sc = new Scanner(System.in);
        Main m = new Main();
        System.out.println(m.bfs(sc.nextInt(), sc.next()));
//        long etime = System.currentTimeMillis();
//        System.out.println((etime - stime));
    }
    private long bfs(int n,String s){
        long ans = 0L;
        Queue<Node> q = new LinkedList<Node>();
        q.offer(new Node(s,n));
        while (!q.isEmpty()){
            Node now = q.poll();
            if(now.s.length()==2||now.s.length()==1){
                ans = (ans+solve(now.s,now.n))%M;
            }else{
                String ts="";
                if((ts=backTrace(now.s))!="") //对于664这种情况会返回“”字符串(即回溯失败),做额外处理
                q.offer(new Node(ts,now.n-1));
                if(now.s.charAt(0)=='4' && (ts=backTrace("6"+now.s))!="") q.offer(new Node(ts,now.n-1));
                else if(now.s.charAt(0)=='6' && (ts=backTrace("1"+now.s))!="") q.offer(new Node(ts,now.n-1));
            }

        }
        return ans;
    }
    private String backTrace(String s){
        String rs = "";
        for(int i =0 ; i<s.length(); i++){
            if(s.charAt(i)=='2') rs+="1";
            else if(s.charAt(i)=='4') rs+="2";
            else if(s.charAt(i)=='6' && (i==s.length()-1||s.charAt(i+1)=='4')) {
                rs += "6";
                i++;
            }
            else if(s.charAt(i)=='1' && (i==s.length()-1||s.charAt(i+1)=='6')) {
                rs += "4";
                i++;
            }
            else
                return "";//回溯失败,返回空字符
        }
        return rs;
    }
    private final int[][] mat = {
            //1, 2, 4, 6, 16,26,41,42,44,46,61,62,64,66
            {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//1
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//2
            {1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},//4
            {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},//6
            {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},//16
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},//26
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},//41
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},//42
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},//44
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},//46
            {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},//61
            {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},//62
            {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},//64
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},//66
    };
    ArrayList<String> ids = new ArrayList<String>(Arrays.asList("1", "2", "4", "6", "16","26","41","42","44","46","61","62","64","66"));
    private long solve(String s, int n){
        int[][] init = new int[1][14]; init[0][0] = 1;
        int[][] m = mat.clone();
        while (n > 0){
            if((n&1)==1) init = mul(init, m);
            m= mul(m,m);
            n>>=1;
        }
        return init[0][ids.indexOf(s)];
    }
    final int M = 998244353;

    private int[][] mul(int[][] init, int[][] m){
        int[][] rc = new int[init.length][m[0].length];
        for(int i =0; i<init.length; i++){
            for(int j=0; j<m[0].length; j++){
                for(int k = 0; k < init[0].length; k++){
                    rc[i][j] = (int)( (rc[i][j]+(long)init[i][k]*m[k][j]%M) %M);//将init[i][k]转成long类型计算
                }
            }
        }
        return rc;
    }
    private class Node{
        String s;
        int n;
        Node(String s, int n){
            this.s = s;
            this.n = n;
        }
    }
}

以上代码在backTrace使用String 所以会产生超时以及空间溢出问题,故使用StringBuffer进行优化,以下是满分代码

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Main m = new Main();
        System.out.println(m.bfs(sc.nextInt(), sc.next()));
    }
    private long bfs(int n,String s){
        long ans = 0L;
        Queue<Node> q = new LinkedList<Node>();
        q.offer(new Node(s,n));
        while (!q.isEmpty()){

            Node now = q.poll();
            if (now.s == "" || now.n < 0) continue;
            if(now.s.length()==2 || now.s.length()==1){
                ans = (ans+solve(now.s,now.n))%M;
            }else{
                q.offer(new Node(backTrace(now.s),now.n-1));

                if(now.s.charAt(0)=='4') q.offer(new Node(backTrace("6"+now.s),now.n-1));
                else if(now.s.charAt(0)=='6') q.offer(new Node(backTrace("1"+now.s),now.n-1));
            }

        }
        return ans;
    }
    private String backTrace(String s){
        StringBuffer rs = new StringBuffer();
        for(int i =0 ; i<s.length(); i++){
            if(s.charAt(i)=='2') rs.append("1");
            else if(s.charAt(i)=='4') rs.append("2");
            else if(s.charAt(i)=='6' && (i==s.length()-1||s.charAt(i+1)=='4')) {
                rs.append("6");
                i++;
            }
            else if(s.charAt(i)=='1' && (i==s.length()-1||s.charAt(i+1)=='6')) {
                rs.append("4");
                i++;
            }
            else
                return "";
        }
        return rs.toString();
    }
    private final int[][] mat = {
            //1, 2, 4, 6, 16,26,41,42,44,46,61,62,64,66
            {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//1
            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//2
            {1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},//4
            {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},//6
            {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},//16
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},//26
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},//41
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},//42
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},//44
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},//46
            {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},//61
            {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},//62
            {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},//64
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},//66
    };
    ArrayList<String> ids = new ArrayList<String>(Arrays.asList("1", "2", "4", "6", "16","26","41","42","44","46","61","62","64","66"));
    private long solve(String s, int n){
        int[][] init = new int[1][14]; init[0][0] = 1;
        int[][] m = mat.clone();
        while (n > 0){
            if((n&1)==1) init = mul(init, m);
            m= mul(m,m);
            n>>=1;
        }
        return init[0][ids.indexOf(s)];
    }
    final int M = 998244353;

    private int[][] mul(int[][] init, int[][] m){
        int[][] rc = new int[init.length][m[0].length];
        for(int i =0; i<init.length; i++){
            for(int j=0; j<m[0].length; j++){
                for(int k = 0; k < init[0].length; k++){
                    rc[i][j] = (int)( (rc[i][j]+(long)init[i][k]*m[k][j]%M) %M);//将init[i][k]转成long类型计算
                }
            }
        }
        return rc;
    }
    private class Node{
        String s;
        int n;
        Node(String s, int n){
            this.s = s;
            this.n = n;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值