此算法模拟
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;
}
}
}