牛客小白91

Bingbong的回文路径

https://ac.nowcoder.com/acm/contest/78807/G

原博客链接:https://blog.nowcoder.net/n/8f19b66f4bc14263958b1c3c398274df
第一次内测小白,记录一下

A

模拟。

import java.io.*;
import java.util.*;
public class Main{
    static int maxn = 200005,n,m,inf=0x3fffffff;
    static long INF = (long)2e18,ans = 0,mod = (int)1e9+7;
    static Scanner sc = new Scanner (System.in);
    static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in),65536);
    static StreamTokenizer st  =new StreamTokenizer(bf);
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[]args) throws IOException{
        new Task().main();
        pw.flush();
    }
    
    static class Task{
    	void main() throws IOException {
    		int T=1;
    		//T=I();
    		while(T-->0) solve();
    	}
    	String a = "...|......_...../.\\....|.|....\\_/\\........";
    	String b = ".........._...../.\\/...|.|....\\_/\\........";
    	void solve() throws IOException{
    		String x ="";
    		for(int i=1;i<=6;i++) x = x+bf.readLine();
    		if(x.compareTo(a)==0)pw.println("m");
    		else if(x.compareTo(b)==0) pw.println("o");
    		else pw.println("p");
        }
    }

}

B

简单博弈。显然必定会消除对方要消除的数,分类讨论即可

import java.io.*;
import java.util.*;
public class Main{
    static int maxn = 200005,n,m,inf=0x3fffffff;
    static long INF = (long)2e18,ans = 0,mod = (int)1e9+7;
    static Scanner sc = new Scanner (System.in);
    static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in),65536);
    static StreamTokenizer st  =new StreamTokenizer(bf);
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[]args) throws IOException{
        new Task().main();
        pw.flush();
    }
    
    static class Task{
    	void main() throws IOException {
    		int T=1;
    		T=sc.nextInt();
    		while(T-->0) solve();
    	}
    	
    	void solve() throws IOException{
    		n=sc.nextInt();
    		int ou=n/2,ji=n-ou;
            if(n%2==1) pw.println("Bing");
            else if (ou%2==1) pw.println("Bing");
            else pw.println("Bong");
        }
    }

}

C

一种简单的路线是先走到与中央格子的横/纵坐标相同的格子,再前进至中央。复杂度为

import java.io.*;
import java.util.*;
public class Main{
    static int maxn = 200005,n,m,inf=0x3fffffff;
    static long INF = (long)2e18,ans = 0,mod = (int)1e9+7;
    static Scanner sc = new Scanner (System.in);
    static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in),65536);
    static StreamTokenizer st  =new StreamTokenizer(bf);
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[]args) throws IOException{
        new Task().main();
        pw.flush();
    }

    static class Task{
    	void main() throws IOException {
    		int T=1;
    		//T=I();
    		while(T-->0) solve();
    	}

    	void solve() throws IOException{
    		n=sc.nextInt();
    		m=sc.nextInt();int k=sc.nextInt();
    		int x=n/2+1,y=m/2+1;
    		while(k-->0) {
    			int a=sc.nextInt(),b=sc.nextInt();
    			boolean f1=false,f2=false;
    			if(Math.abs(x-a) >= Math.min(Math.min(x, n-x+1), Math.min(b, m-b+1)))f1=true;
    			if(Math.abs(y-b) >= Math.min(Math.min(a, n-a+1), Math.min(y, m-y+1)))f2=true;
    			if(f2&&f1) continue;
    			ans++;
    		}
    		pw.println(ans);
        }
    }

}

D

容斥。 记录 的阶乘, 记录前导零数当前总数,记录答案时减掉即可

import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main{
    static int maxn = 200005,n,m,inf=0x3fffffff;
    static long INF = (long)2e18,ans = 0,mod = (int)1e9+7;
    static Scanner sc = new Scanner (System.in);
    static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in),65536);
    static StreamTokenizer st  =new StreamTokenizer(bf);
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[]args) throws IOException{
        new Task().main();
        pw.flush();
    }
    static final int I() throws IOException {
        st.nextToken();
        return (int)st.nval;
    }
    static String S() throws IOException{
    	String res = bf.readLine();
    	while(res.equals(""))res=bf.readLine();
    	return res;
    }
    
    static class Task{
    	void main() throws IOException {
    		int T=1;
    		//T=I();
    		while(T-->0) solve();
    	}

    	char[]s;
    	long fac[] = new long[maxn];
    	
    	void solve() throws IOException{
    		n=I();
    		s = ("*"+S()).toCharArray();
    		long sum0 = 0;
    		for(int i=0;i<=n;i++) {
    			if(i==0) fac[i]=1;
    			else fac[i] = fac[i-1]*2%mod;
    		}
    		for(int i=1;i<=n;i++) {
    			sum0 = sum0*2%mod;
    			if(s[i-1]=='0') sum0++;
    			if((s[i]-'0')%2==1) continue;
    			ans = (ans + fac[i-1])%mod;
    			ans = (ans - sum0 + mod)%mod;
    		}
    		pw.println(ans);
        }
    }

}

E

维护一个 的二维数组表示每个字符的下一个位置在哪,然后从 的每一个位置出发得到含 且无 的串,将串能到达最右边的位置记录到答案中。才知道叫序列自动机
复杂度

import java.io.*;
import java.util.*;
public class Main{
    static int maxn = 200005,n,m,inf=0x3fffffff;
    static long INF = (long)2e18,ans = 0,mod = (int)1e9+7;
    static Scanner sc = new Scanner (System.in);
    static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in),65536);
    static StreamTokenizer st  =new StreamTokenizer(bf);
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[]args) throws IOException{
        new Task().main();
        pw.flush();
    }
    static final int I() throws IOException {
        st.nextToken();
        return (int)st.nval;
    }
    static String S() throws IOException{
    	String res = bf.readLine();
    	while(res.equals(""))res=bf.readLine();
    	return res;
    }
    
    static class Task{
    	void main() throws IOException {
    		int T=1;
    		//T=I();
    		while(T-->0) solve();
    	}

    	char[]s;
    	int [][]dp = new int [maxn][26];
    	char[]arr= "ACCEPT".toCharArray();
    	
    	void solve() throws IOException{
    		n=I();m=I();
    		s = (")"+S()).toCharArray();
    		for(int i=n;i>=0;i--) {
    			if(i==n) Arrays.fill(dp[i], n+1);
    			else {
    				dp[i]= Arrays.copyOf(dp[i+1], 26);
    				dp[i][s[i+1]-'A']=i+1;
    			}
    		}
    		for(int i=0;i+m<=n;i++) {
    			if(s[i+1]=='W') continue;
    			int l=i+1,r=1+i;
              	int wl=n+1,ar=-1;//串最左w,最右a
    			int p=i;
    			wl=dp[p]['W'-'A'];
    			for(int j=0;j<6;j++) {
    				p = dp[p][arr[j]-'A'];
    				if(p>n) break;
    				r=p;
    			}
    			if(p>n) continue;
    			p=i;
    			for(int j=0;j<5;j++) {
    				int x = dp[p][0];
    				if(x>r) break;
    				ar = x;
    				p=dp[p][arr[j]-'A'];
    			}
    			if(wl<ar && ar<r) continue;
                ar = Math.min(n,wl<n?dp[wl][0]-1:n);
                if(r-l+1<m) r = m+l-1;
                ans += Math.max(0, ar-r+1);
    		}
    		pw.println(ans);
        }
    }

}

F

都说典,但我真看半天。。
考虑逐位两点贡献。设 为之前一个数此位为 且包含这个数的所有区间之和,每次累加计算答案即可。
复杂度

import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main{
    static int maxn = 200005,n,m,inf=0x3fffffff;
    static long INF = (long)2e18,ans = 0,mod = (int)1e9+7;
    static Scanner sc = new Scanner (System.in);
    static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in),65536);
    static StreamTokenizer st  =new StreamTokenizer(bf);
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[]args) throws IOException{
        new Task().main();
        pw.flush();
    }
    static final int I() throws IOException {
        st.nextToken();
        return (int)st.nval;
    }
    static String S() throws IOException{
    	String res = bf.readLine();
    	while(res.equals(""))res=bf.readLine();
    	return res;
    }
    
    static class Task{
    	void main() throws IOException {
    		int T=1;
    		//T=I();
    		while(T-->0) solve();
    	}

    	boolean[][]a = new boolean[maxn][20];
    
    	void solve() throws IOException{
    		n=I();
    		for(int i=1;i<=n;i++) {
    			int x=I();
    			Arrays.fill(a[i], false);
    			for(int j=19;j>=0;j--) {
    				if(x<1<<j) continue;
    				a[i][j]=true;
    				x-=1<<j;
    			}
    		}
    		for(int j=0;j<=19;j++){
                long sum0=0,sum1=0,val=1<<j;
                for(int i=1;i<=n;i++){
                    if(a[i][j]) ans = (ans + sum0*(n-i+1)%mod*val%mod)%mod;
                    else ans = (ans + sum1*(n-i+1)%mod*val%mod)%mod;
                    if(a[i][j]) sum1 += i;
                    else sum0+=i;
                }
            }
            pw.println(ans*2%mod);
        }
    }

}

G

倍增+哈希
思路挺简单粗暴的,就是维护树根向下的哈希和叶节点向上的哈希,分类讨论即可。复杂度
严谨做法是轻重链剖分+后缀数组, 但是不会

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

public class Main {
	static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in),65535);
	static StreamTokenizer st = new StreamTokenizer(bf);
	static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
	static Scanner sc = new Scanner(System.in);
	static int n,m,maxn=200005,inf = 0x3f3f3f3f;
	static long ans=0,mod=(int)1e9+7,INF=(long)2e18;
	public static void main(String[]args) throws IOException{
		new Task().main();
		pw.flush();
	}
	static int I() throws IOException {
		st.nextToken();
		return (int)st.nval;
	}
	static String S() throws IOException {
		String res=bf.readLine();
		while(res.equals("")) res = bf.readLine();
		return res;
	}
	
	static class Task{
		void main()throws IOException{
			int t=1;
			//t=I();
			while(t-->0) solve();
		}
		
		Vector<Vector<Integer>> g = new Vector<>();
		char[]s;
		long base=2333;
		int []dep = new int[maxn>>1];
		long []hs = new long[maxn>>1];//自根向下遍历的hash值
		int [][]dp = new int[maxn>>1][20];//倍增
		long [][]hash = new long[maxn>>1][20];//自下向上的hash值
		long []fac = new long[1<<20];
		
		private void solve() throws IOException {
			n=I();
			for(int i=0;i<=n;i++) g.add(new Vector<>());
			for(int i=0;i<1<<20;i++) {
				if(i==0) fac[i]=1;
				else fac[i] = fac[i-1]*base%mod;
			}
			s = ("0"+S()).toCharArray();
			s[0]=0;
			for(int i=1;i<=n;i++) {
				int fa=I();
				if(i==1) continue;
				g.get(fa).add(i);
			}
			dfs1(1,0,s[0]);
			int q = I();
			while(q-->0) {
				int u=I(),v=I();
				int lca = dfs2(u,v);
				int len = dep[u]+dep[v]-dep[lca]*2+1;//链长
				long l=0,r=0;//两链hash
				long left = dep[u]-dep[lca]+1;//u->lca的节点数量
				int uu=u,vv=v;//u--uu,vv--v,两段链
				int siz = len/2 + (len%2==1?1:0);
				if(left >= siz+1) {
					uu = get_fa(u,siz-1);
					vv = len%2==1?uu:dp[uu][0];
					l = (hs[u]-hs[dp[uu][0]]*fac[siz]%mod+mod)%mod;
					int len2=dep[vv]-dep[lca]+1,len3=siz-len2;
					r = (get_fa_hash(vv,len2-1)*fac[len3]%mod + hs[v]-hs[lca]*fac[len3]%mod+mod)%mod;
				}
				else {
					vv = get_fa(v,siz-1);
					uu = len%2==1?vv:dp[vv][0];
					r = (hs[v]-hs[dp[vv][0]]*fac[siz]%mod+mod)%mod;
					int len2=dep[uu]-dep[lca]+1,len3=siz-len2;
					l = (get_fa_hash(uu,len2-1)*fac[len3]%mod + hs[u]-hs[lca]*fac[len3]%mod+mod)%mod;
				}
				pw.println(l==r ? "YES" : "NO");
			}
		}

		private long get_fa_hash(int v, int t) {//v到v向上第t个点的hash
			// TODO Auto-generated method stub
			long res=s[v];
			for(int j=0;j<20 && t>0;j++,t>>=1) {
				if(t%2==1) {
					//pw.println("j:"+j);
					res = (res*fac[1<<j]%mod + hash[v][j] - s[v]*fac[1<<j]%mod+mod)%mod;
					v = dp[v][j];
				}
			}
			return res;
		}

		private int get_fa(int v, int t) {
			// TODO Auto-generated method stub
			for(int j=0;j<20 && t>0;j++,t>>=1) {
				if(t%2==1) v = dp[v][j];
			}
			return v;
		}

		private int dfs2(int u, int v) {
			// TODO Auto-generated method stub
			if(dep[u]>dep[v]) {
				int t=u;u=v;v=t;
			}
			int t = dep[v]-dep[u];
			for(int j=0;j<20 && t>0;j++,t>>=1) {
				if(t%2==1) v = dp[v][j];
			}
			if(u==v) return u;
			for(int j=19;j>=0;j--) {
				if(dp[u][j] != dp[v][j]) {
					u = dp[u][j];v = dp[v][j];
				}
			}
			return dp[u][0];
		}

		private void dfs1(int i, int fa, long val) {//当前结点,父节点,hash前缀和
			// TODO Auto-generated method stub
			dep[i] = dep[fa]+1;
			hs[i] = (val*base+s[i])%mod;
			dp[i][0] = fa;
			hash[i][0] = s[i]*base + s[fa];
			for(int j=1;j<20;j++) {
				dp[i][j] = dp[dp[i][j-1]][j-1];
				hash[i][j] = (hash[i][j-1]*fac[(1<<j-1)]%mod + hash[dp[i][j-1]][j-1] - s[dp[i][j-1]]*fac[(1<<j-1)]%mod+mod)%mod;
			}
			for(int x:g.get(i)) {
				if(dep[x]==0) dfs1(x,i,hs[i]);
			}
		}
	}
}

全部评论

相关推荐

11-11 14:21
西京学院 C++
Java抽象练习生:教育背景放最前面,不要耍小聪明
点赞 评论 收藏
分享
牛舌:如果我不想去,不管对方给了多少,我一般都会说你们给得太低了。这样他们就会给下一个offer的人更高的薪资了。
点赞 评论 收藏
分享
2 收藏 评论
分享
牛客网
牛客企业服务