牛客小白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]);
			}
		}
	}
}

全部评论

相关推荐

03-10 11:23
门头沟学院 Java
鹿LF:计算机面试就跟数学题一样,没什么实际价值,但只能这么筛选,本质是考察你的努力,智力和学习能力
点赞 评论 收藏
分享
点赞 评论 收藏
分享
04-24 13:51
已编辑
西安电子科技大学 Java
👋个人背景:211计算机混子,代码能力一般,春招急头白脸参加央国企最后拿下这两个offer👏offer1:中广核工程公司驻陆丰仪控调试,待遇19+4,离家1800km💯offer2:张家口卷烟厂待遇未知,应该有13个(猜测),离家500km牛油们帮忙选一下,家里人不是很喜欢卷烟厂这个offer,但是蜀黍烟草局下岸了
鸿雁于飞:先说offer1:中广核工程公司驻陆丰仪控调试(待遇19+4) 中广核这艘央企大船还是很稳的,集团综合效益稳居央企前列。但你得搞清楚,这个19+4的"19"是总包,不是到手数——招聘宣传待遇里把所有能算的都算进去了,饭卡福利积分啥的全包含,有牛油分享实际到手大概打七折。试用期到手可能就四五千的水平,转正后基本工资4800左右,其余靠绩效、年终、大修费撑着。不过核电的工作环境有点"牢笼感"——核电站位置偏僻,远离繁华都市。工程公司是承包商性质,干活比业主公司累,而且大概率要经常出差,有的岗位年出差天数100天以上。最大问题是你这1800km的距离过于离谱,核电员工工作强度最小的时候一周也就回一次家,离得远回家成本高,夫妻感情和亲子关系都是现实考验。说白了:高薪是拿青春和生活换的。 再来看offer2:张家口卷烟厂(待遇约13个) 张家口卷烟厂是河北中烟下属三家卷烟厂之一,河北中烟主打的"荷花"系列连续多年位居全国高端卷烟品牌销量前列。烟草系统薪资由基本工资+绩效+年终奖构成,综合年薪普遍显著高于当地平均水平,六险二金齐全,福利拉满。有人问"13个是不是太平平无奇了"——关键张家口是四线城市,生活成本低,这13万的购买力相当于深圳的二十多万。离家500km,开车半天到家,周末回趟家完全可行,幸福感直接上两个档次。中广核的牛油说了句大实话: "哪个核电站好?永远是离家近的那个最好。" 选烟厂同理。 但是,卷烟厂的坑你得清楚: 首先卷烟厂和烟草局不一样,卷烟厂是生产操作类岗位,很多要三班倒。报考条件明确写了要能"胜任夜班工作和长时间站立工作"。一线操作工每天盯着流水线卷烟,工作内容高度重复,有入职的人描述为"食之无味弃之可惜"。有牛油直言"卷烟厂和商业性质的烟草公司不一样,前者很坑很累"。其次你家里人不是不喜欢,而是担心你这211计算机科班出身,进了烟厂干操作工,技能会快速退化,未来如果行业改革,技术壁垒不高,转行比较困难。等你干两年再跳出来,技术栈全忘干净了,回头再去敲代码,发现连应届生都卷不过。 老牛油的灵魂三问: 1. 你是更怕穷,还是更怕想家? 如果特别恋家的人跑1800km之外,第一年哭鼻子的概率高达80%。陆丰那地方偏僻单调,核电基地又远又闷,闲下来除了打游戏没啥娱乐,社交圈也窄。找个对象都费劲——牛油亲测核电站"狼多肉少"。 2. 你的代码能力有多"一般"? 如果真的一般,仪控调试和你专业匹配度不算高,这活儿主要是工程改造设计、现场实施管理、在建机组设计审查等,偏工程向而非纯软开。干两年后跳回互联网赛道,竞争力不一定有明显提升。反倒是烟厂不需要你写代码,进去就是稳定躺平。 3. 烟草局下岸这事儿会不会让你耿耿于怀? 如果烟草局是你第一志愿,烟厂只是plan B,那得想清楚:进去了可能每天看着天花板想"如果当初去了烟草局该多好",这种内耗比钱少还折磨人。如果你能接受"反正都是烟草系统,先进去再说"的心态,那倒无所谓。 一句话总结: 如果年轻想拼想闯做技术积累,中广核虽然累和远,但简历上央企核电的金字招牌确实有含金量,加上到手收入在这两个选项里确实更高,考虑到你个人经济情况和家庭状况,假如家里不需要你常回去照顾,家里有兄弟姐妹帮手分担,那先去核电待三四年,积累经验再跳槽也不失为一步棋。 如果想安稳过日子离家近当"人上人",烟厂低线生活成本加持,加上稳定的编制和福利体系,在张家***得滋润,幸福感吊打陆丰。尤其家里人是那种离不开你的,有烟厂的稳定且离家近,比任何高薪都实在。
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务