zoukankan      html  css  js  c++  java
  • Contest 210205

    题目已存档至硬盘

    万能遥控器

    第一道就是毒瘤模拟,TAT.先不改了,记录一下我的代码和标程吧.

    #include <bits/stdc++.h>
    
    using namespace std;
    int n;
    char ip[100][50],ans[100][50];
    string s;
    
    inline int read()
    {
    	int s=1,x=0;char c=getchar();
    	while(c>'9'||c<'0'){if(c=='-')s=0;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
    	return s?x:-x;
    }
    
    bool special(int &len)
    {
    	for(int i=0;i<len-2;i++)
    	{
    		if(s[i]==':'&&s[i+1]==':'&&s[i+2]==':')
    			return true;
    	}
    	return false;
    }
    
    void solve()
    {
    	for(int j=0;j<100;j++)
    		{
    			for(int k=0;k<50;k++)
    			{
    				ip[j][k]='x';
    				ans[j][k]='x';
    			}
    		}
    		cin>>s;
    		int len=s.length(),flag=-1,p=0,p_group=-1;
    		if(special(len))
    		{
    			cout<<"INVALID
    ";
    			return;
    		}
    		for(int j=0;j<len;j++)
    		{
    			if(j<len-1&&s[j]==':'&&s[j+1]==':')
    			{
    				if(flag==-1)
    					flag=p;	
    				else
    				{
    					cout<<"INVALID
    ";
    					return;
    				}
    				p++;
    				j++;
    				p_group=-1;
    			}
    			else if(s[j]==':')
    			{
    				p++;
    				p_group=-1;
    			}
    			else
    				ip[p][++p_group]=s[j];
    		}
    		if((p<7&&flag==-1) || p>7 || (p==6 && flag>=0))
    		{
    			cout<<"INVALID
    ";
    			return;
    		}
    		for(int j=0;j<=p;j++)
    		{
    			int tot=0;
    			for(int k=0;k<50;k++)
    			{
    				if(ip[j][k]=='x') break;
    				else if((ip[j][k]>='0'&&ip[j][k]<='9') || (ip[j][k]>='A'&&ip[j][k]<='F'))
    				{
    					tot++;
    				}
    				else
    				{
    					cout<<"INVALID
    ";
    					return;
    				}
    			}
    			if(tot>4)
    			{
    				cout<<"INVALID
    ";
    				return;
    			}
    			else
    			{
    				for(int k=0;k<4-tot;k++)
    				{
    					ans[j][k]='0';
    				}
    				for(int k=4-tot;k<4;k++)
    				{
    					ans[j][k]=ip[j][k-4+tot];
    				}
    			}
    		}
    		for(int j=0;j<=p;j++)
    		{
    			for(int k=0;k<4;k++)
    			{
    				if(ans[j][k]=='x')
    				{
    					cout<<"INVALID
    ";
    					return;
    				}
    				cout<<ans[j][k];
    			}
    			if(j!=p) cout<<':';
    			if(j==flag)
    			{
    				for(int k=1;k<=(7-p);k++)
    				{
    					printf("0000");//bug,but solved
    					if(k+j!=7) putchar(':');
    				}
    			}
    		}
    		cout<<endl;
    }
    
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		solve();
    	}
    	
    	return 0;
    }
    

    137行,学OI来写的最多的一次.

    标程:

    #include <bits/stdc++.h>
    using namespace std;
    char s[100], a[100];
    int main()
    {
    	freopen( "ipv6.in", "r", stdin ); freopen( "ipv6.out", "w", stdout ); int n;
    	scanf( "%d
    ", &n );
    	for ( int ii = 1; ii <= n; ii++ )
    	{
    		memset( s, '0', sizeof(s) );
    		memset( a, '0', sizeof(a) );
    		char	c;
    		int	p1 = 0, p2 = 0, p3 = 0, p4 = 0, k = 0, point = 0;
    		while ( (c = getchar() ) != EOF && c != '
    ' )
    		{
    			s[++k] = c;
    			if ( c == ':' )
    			{
    				p1 = 0; p2++;
    			}else p1++;
    			if ( p1 > 4 || p2 > 7 )
    				p4 = 1;
    			if ( c == ':' && s[k - 1] == ':' )
    			{
    				p3++; point = k;
    			}
    			if ( p3 > 1 )
    				p4 = 1;
    		}
    		if ( !p3 && p2 < 7 )
    			p4 = 1;
    		if ( p3 && p2 == 7 && point != 2 && point != k )
    			p4 = 1;
    		for ( int i = 1; i <= k; i++ )
    			a[i] = s[k - i + 1];
    		if ( p4 )
    		{
    			printf( "INVALID
    " ); continue;
    		}
    		int q = 0;
    		p1 = 0;
    		for ( int i = 1; i <= k; i++ )
    		{
    			s[++q] = a[i];
    			p1++;
    			if ( a[i] == ':' )
    			{
    				q--;
    				while ( p1 < 5 )
    				{
    					s[++q] = '0';
    					p1++;
    				}
    				s[++q]	= ':';
    				p1	= 0;
    				if ( a[i + 1] == ':' )
    				{
    					while ( p2 <= 7 )
    					{
    						for ( int j = 1; j <= 4; j++ )
    							s[++q] = '0';
    						s[++q] = ':';
    						p2++;
    					}
    					q--;
    					p1 = 4;
    				}
    			}
    		}
    		for ( int i = 39; i >= 1; i-- )
    			printf( "%c", s[i] );
    		cout << endl;
    	}
    	return(0);
    }
    

    收藏钻石

    这道题很有意思呀,乍一看以为是二分答案,结果要分成2个陈列架.然后想到用一块板子将钻石们分开,左右2边分别二分答案,但这样复杂度是 O ( n 2 l o g   n ) O(n^2 log n) O(n2log n).考虑优化,首先第一层枚举板子的循环肯定不能再优化了,难道优化二分答案?

    结果真的是优化二分答案,考场上想出了一种DP方案.
    若 m 表 示 所 有 满 足 a [ i ] − a [ i − m ] ≤ k 的 m 的 最 小 值 , 则 f [ i ] = m a x ( f [ i − 1 ] , m + 1 ) 若m表示所有满足a[i]-a[i-m]le k的m的最小值,则\f[i]=max(f[i-1],m+1) ma[i]a[im]km,f[i]=max(f[i1],m+1)
    然后正向和反向分别DP一次,再插板,即可求出最终答案.

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N=5e4+5;
    int n,k,s[N],ans,l[N],r[N];
    
    inline int read()
    {
    	int s=1,x=0;char c=getchar();
    	while(c>'9'||c<'0'){if(c=='-')s=0;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
    	return s?x:-x;
    }
    
    
    int main()
    {
    	freopen("diamond.in","r",stdin);
    	freopen("diamond.out","w",stdout);
    	
    	n=read();
    	k=read();
    	for(int i=1;i<=n;i++)
    	{
    		s[i]=read();
    	}
    	sort(s+1,s+n+1);
    	
    	l[1]=r[n]=1;
    	l[0]=r[n+1]=0;
    	for(int i=2;i<=n;i++)
    	{
    		int x=l[i-1];
    		while(s[i]-s[i-x+1]<=k&&i-x>=0)
    		{
    			x++;
    		} 
    		l[i]=max(l[i-1],x-1);
    //		cout<<l[i]<<' ';
    	}
    //	cout<<endl;
    	for(int i=n-1;i>=1;i--)
    	{
    		int x=r[i+1];
    		while(s[i+x-1]-s[i]<=k&&i+x<=n+1)
    		{
    			x++;
    		}
    		r[i]=max(r[i+1],x-1);
    //		cout<<r[i]<<' '; 
    	}
    //	cout<<endl;
    	for(int i=0;i<=n;i++)
    	{
    		ans=max(ans,l[i]+r[i+1]);
    	}
    	cout<<ans<<endl;
    	
    	return 0;
    }
    

    sequence

    最难的一道DP.看了题解,还结合了另外的算法,于是先去把字符串哈希做了.

    决定以后hash的mod就用1e9+7和1e7+7,base为131

    #include <bits/stdc++.h>
    #define ll long long
    
    using namespace std;
    const ll N=1e4+5,mod=1e9+7,base=131;
    int n,ans;
    ll a[N];
    string s;
    
    int main()
    {	
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		cin>>s;
    		int len=s.length();
    		for(int j=0;j<len;j++)
    		{
    			a[i]=(a[i]*base+(ll)s[j])%mod;
    		}
    	}
    	sort(a+1,a+n+1);
    	for(int i=1;i<n;i++)
    	{
    		if(a[i]==a[i+1]) ans++;
    	}
    	cout<<n-ans;
    
    	return 0;
    }
    

    回到这道题,我的思考过程落脚于将数列分开的"切点".切点前数列的长度一定小于等于切点后数列的长度.然后就开始愉快的正向DFS模拟了,每次可以将剩下没切的数列切下一块,但切的长度,要么是小于等于剩下长度的二分之一,要么是等于剩下的长度(切完).中途会比较本次切的部分与上次切的部分的大小.

    一份代码就出炉了:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N=5e3+5,mod=1e9+7;
    int n,ans;
    int s[N];
    
    bool cmp(const int &l1,const int &r1,const int &l2,const int &r2)//if l1 to r1>l2 to r2
    {
    	if(r1-l1>r2-l2)
    		return true;
    	else if(r1-l1==r2-l2)
    	{
    		for(int i=l1;i<=r1;i++)
    		{
    			if(s[i]<s[l2+i-l1]) return false;
    			if(s[i]==s[l2+i-l1]&&i==r1) return false;
    		}
    		return true;
    	}
    	else return false;
    }
    
    void solve(int l,int r,int pre_l,int pre_r)
    {
    	if(l==r)
    	{
    		(ans+=1)%=mod;
    		return;
    	}
    	if(s[l]==0) return;
    	int pre_size=pre_l-pre_r+1;
    	for(int i=pre_size;i<=((r-l+1)/2);i++)
    	{
    		if(cmp(l,l+i-1,pre_l,pre_r))
    			solve(l+i,r,l,l+i-1);
    	}
    	if(cmp(l,r,pre_l,pre_r))
    	{
    		solve(r,r,l,r);
    	}
    }
    
    int main()
    {
    	freopen("sequence.in","r",stdin);
    	freopen("sequence.out","w",stdout);
    	
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%1d",&s[i]);
    	}
    	solve(1,n,0,0);
    	cout<<ans%mod;
    	
    	return 0;
    }
    

    首先DFS不是正解DP,复杂度就被卡掉了,其次正确性还出了问题,另外,根本就没考虑到cmp函数会是正解程序优化的着重部分,复杂度Up.

    如果复杂度过高,n=10的部分解也有30分,也是个不错的选择,但因为正确性问题,最终只得到了10分.

    开始正解分析:

    本题的答案需要mod 1e9+7,显然考虑DP求总方案数.定义f[i][j]为取[i,j]为最后一段的总方案数,那么f[i][j]可以由f[k][i-1]转移得到(k<i-1).

  • 相关阅读:
    Ubuntu 只能用guest登录的问题修复
    Ubuntu下编译C语言程序(同时给编译生成的文件命名)
    设置PYTHONIOENCODING
    Ubuntu安装atom
    R语言中将数据框(data.frame)中字符型数据转化为数值型
    修改记事本默认编码为UTF-8
    Java虚拟机浅探
    制作宅基腐主页 && 制作个人简历--材料:BootStrap
    尝试用有限状态机解决一道算法题
    OOP,WEB开发实用小技巧
  • 原文地址:https://www.cnblogs.com/huaruoji/p/14425562.html
Copyright © 2011-2022 走看看