• MZOI20200516题解


    下面是我在考场上写的题解

    T1

    这明显是一道“查重”的题,也就是在这个字符串中不能有两个相同的ans+i的字符串。

    我们先作以下规定

    字符串为txt,长度为len

    看到这里,我们心里要有些瞎()想,怎么记录这个呢?

    最开始想到了二分,但是发现不可做,因为两个相同的字符串可能出现在任何地方,如果这样二分答案的话,虽然答案具有单调性,可是需要枚举l-mid种可能性,所以我们不用。
    我不会告诉你我不用的原因是因为我不会二分

    然后我就想到了kmp匹配,如果我从开始匹配起,每一次不仅记录next数组,我还新增加一个lon数组以用来记录长度,这样的话就可以知道重复的长度有多少,所以我一开始的代码就出来了

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define ri register int
    #define Starseven main
    using namespace std;
    const int N=120;
    char txt[N];
    int ioi[N];
    int lon[N];
    
    void Pre_Next(){
    	int s1=0,s2;
    	ioi[0]=s2=-1;
    	int ans=0;
    	int len2=strlen(txt),len=0;
    	while(s1<len2){
    		if(s2==-1||txt[s1]==txt[s2]){
    			if(s2==-1) len=0;
    			else len++;
    			ioi[++s1]=++s2;
    			lon[s1]=len;
    			ans=max(ans,len);
    		}
    		else{
    			ans=max(ans,len);
    			s2=ioi[s2];
    			len=lon[s2];
    		}
    	}
    	cout<<ans<<endl;
    	return ;
    }
    
    int Starseven(void){
    	cin>>txt;
    	Pre_Next();
    	return 0;
    }
    
    

    样例毫无疑问地过了,然后我手造了一组数据

    [fghgwooh ]

    我的输出是0,结果应该是1,我就开始思考了,为什么呢??

    我又想到了一点,然后输出了next数组,对了!next数组只是从开始匹配,如果中间有什么东西的话就不得行了,所以我们应该枚举起点,然后做len次kmp匹配。

    所以我改了一下:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define ri register int
    #define Starseven main
    using namespace std;
    const int N=120;
    char txt[N],a[N];
    int ioi[N];
    int lon[N];
    int ans=0;
    	
    void Pre_Next(int len2){
    	int s1=0,s2;
    	memset(ioi,0,sizeof(ioi));
    	memset(lon,0,sizeof(lon));
    	ioi[0]=s2=-1;
    	int len=0;
    	while(s1<len2){
    		if(s2==-1||txt[s1]==txt[s2]){
    			if(s2==-1) len=0;
    			else len++;
    			ioi[++s1]=++s2;
    			lon[s1]=len;
    			ans=max(ans,len);
    		}
    		else{
    			ans=max(ans,len);
    			s2=ioi[s2];
    			len=lon[s2];
    		}
    	}
    	return ;
    }
    
    int Starseven(void){
    	cin>>a;
    	int l=strlen(a);
    	for(ri i=0;i<l;i++){
    		for(ri j=i;j<l;j++) txt[j-i]=a[j];
    		Pre_Next(l-i);
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

    然后就没管了。

    T2

    T2不想多讲,我在考场上一看便是最小生成树,粘代码:

    (别急,最小生成树可不可以用于最大)

    这是个问题。

    额,关键是,如果我们将权值取反然后求最小生成树,不就变成了最大生成树了吗??

    (当然,这是我考场的想法)

    代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define ri register int
    #define Starseven main
    using namespace std;
    const int N=200000+20;
    int read();
    void write(int);//要记得自己加换行和空格 
    int n,m,all,ans,fa[N>>1];
    
    struct node{
    	int from,to,va;
    }dis[N<<1];
    
    bool cmp(const node &a,const node &b){
    	return a.va<b.va;
    }
    
    int Find(int x){
    	if(fa[x]==x) return x;
    	else return fa[x]=Find(fa[x]);
    }
    
    void Merge(int fx,int fy){
    	fa[fx]=fy;return ;
    }
    
    int Starseven(void){
    	n=read(),m=read();
    	for(ri i=1;i<=m;i++){
    		dis[i].from=read();
    		dis[i].to=read();
    		dis[i].va=read();
    		all+=dis[i].va;
    		dis[i].va=-dis[i].va;
    	}
    	for(ri i=1;i<=n;i++) fa[i]=i;
    	sort(dis+1,dis+1+m,cmp);
    	int ti=0;
    	for(ri i=1;i<=m;i++){
    		int x=dis[i].from,y=dis[i].to;
    		int fx=Find(x),fy=Find(y);
    		if(fx==fy) continue;
    		Merge(fx,fy);
    		ans+=dis[i].va;
    		ti++;
    		if(ti==n-1) break;
    	}
    	write(all+ans);
    	return 0;
    } 
    
    int read(){
    	char ch=getchar();
    	int re=0,op=1;
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') op=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		re=(re<<3)+(re<<1)+ch-'0';
    		ch=getchar();
    	}
    	return re*op;
    }
    
    void write(int x){
    	if(x<0){
    		putchar('-');
    		x=-x;
    	}
    	if(x>9) write(x/10);
    	putchar(x%10+'0');
    	return ;
    }
    

    T3

    现在我们来到了T3。

    我一看编=便知道是容斥原理,主要是枚举子集这里,幸好我在牛客网网课上看了的

    for(ri x=sc;x;x=(x-1)&sc)
    

    其他的不多说,然后就是long long的问题

    #include<cstdio>
    #include<iostream>
    #define ri register int 
    #define Starseven main
    #define ll long long
    using namespace std;
    int read();
    void write(ll);//要记得自己加换行和空格 
    int n;
    ll have[1<<11];
    ll ans=0;
    
    ll Judge(int x){
    	int num=0;
    	while(x){
    		if(x&1) num++;
    		x>>=1;
    	}
    	if(num%2!=0) return 1;
    	else return -1;
    }
    
    ll Power(ll x){
    	return (x-1)*x/2;
    }
    
    void init(){
    	freopen("3.in","r",stdin);
    //	freopen("3.out","w",stdout);
    }
    
    int Starseven(void){
    	//init();
    	n=read();
    	for(ri i=1;i<=n;i++){
    		char ch=getchar();
    		while(ch<'0'||ch>'9') ch=getchar();
    		int sc=0,re=0;
    		while(ch>='0'&&ch<='9'){
    			int gg=ch-'0';
    			re=1<<gg;
    			sc=sc|re;
    			ch=getchar();
    		}
    		for(ri x=sc;x;x=(x-1)&sc) have[x]++;
    	}
    	int all=(1<<10)-1;
    	for(ri x=all;x;x--){
    		if(have[x]<2) continue;
    		ans=ans+Power(have[x])*Judge(x);
    	}
    	write(ans);
    	return 0;
    }
    
    int read(){
    	char ch=getchar();
    	int re=0,op=1;
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') op=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		re=(re<<3)+(re<<1)+ch-'0';
    		ch=getchar();
    	}
    	return re*op;
    }
    
    void write(ll x){
    	if(x<0){
    		putchar('-');
    		x=-x;
    	}
    	if(x>9) write(x/10);
    	putchar(x%10+'0');
    	return ;
    }
    

    关键来了,我闲得无聊,于是就写了个暴力程序对拍,小数据都对了,可是到了n=100000,时,我的程序输出和我的对拍程序输出不同

    [What;can;I ;do;? ]

    于是我就没有管了。


    以上的东西都是我在考场上写的东西,之后的东西得看我的成绩。(哈哈哈


    下面是比赛后写的:

    T1&T3得了分,T2爆炸

    事实证明当你春风得意的时候,应该检查一下long long

    我哭了,哈哈哈哈哈哈哈

    现在附上T2正解

    #include<cstdio>
    #include<iostream>
    #define ri register int 
    #define Starseven main
    #define ll long long
    using namespace std;
    int read();
    void write(ll);//要记得自己加换行和空格 
    int n;
    ll have[1<<11];
    ll ans=0;
    
    ll Judge(int x){
    	int num=0;
    	while(x){
    		if(x&1) num++;
    		x>>=1;
    	}
    	if(num%2!=0) return 1;
    	else return -1;
    }
    
    ll Power(ll x){
    	return (x-1)*x/2;
    }
    
    void init(){
    	freopen("3.in","r",stdin);
    //	freopen("3.out","w",stdout);
    }
    
    int Starseven(void){
    	//init();
    	n=read();
    	for(ri i=1;i<=n;i++){
    		char ch=getchar();
    		while(ch<'0'||ch>'9') ch=getchar();
    		int sc=0,re=0;
    		while(ch>='0'&&ch<='9'){
    			int gg=ch-'0';
    			re=1<<gg;
    			sc=sc|re;
    			ch=getchar();
    		}
    		for(ri x=sc;x;x=(x-1)&sc) have[x]++;
    	}
    	int all=(1<<10)-1;
    	for(ri x=all;x;x--){
    		if(have[x]<2) continue;
    		ans=ans+Power(have[x])*Judge(x);
    	}
    	write(ans);
    	return 0;
    }
    
    int read(){
    	char ch=getchar();
    	int re=0,op=1;
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') op=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		re=(re<<3)+(re<<1)+ch-'0';
    		ch=getchar();
    	}
    	return re*op;
    }
    
    void write(ll x){
    	if(x<0){
    		putchar('-');
    		x=-x;
    	}
    	if(x>9) write(x/10);
    	putchar(x%10+'0');
    	return ;
    }
    
  • 相关阅读:
    枚举求解,也叫暴力破解
    多线程之线程的中止
    beginners with the Multithreading programming
    EditBox control Update Problem (A CString type EditBox control in a loop cannot be updated immidiately)
    有关多线程的一些技术问题
    多线程编程基础知识
    VC的若干实用小技巧 (如何干净的删除一个类)
    进入MFC讲坛的前 (Window 程序详细分析)
    Multithreading using MFC in Plain English: Part I
    关于在VS2005环境下无法从源视图切换到设计视图的解决方案
  • 原文地址:https://www.cnblogs.com/starseven/p/12942233.html
Copyright © 2020-2023  润新知