zoukankan      html  css  js  c++  java
  • 第一次小赛

    A.Gym - 102152J 暴力map

    传送门

    题意:

    给一个n*m的矩阵,每一行内的数字可以随意交换,矩阵的美丽值定义为(a[i][j]=a[i-1][j])的对数。问矩阵调整后最大的美丽值。

    n和m都是1e3的,矩阵内数值范围是1-1e8

    做法:

    用二维map维护,(mp[i][j]) 代表第 (i) 行有几个数字 (j)

    最后两行之间共同拥有的数字的数量取min加到答案里。

    闲话:

    一开始还有点担心这复杂度,自从会用map之后,什么数组会爆掉的全用map一套解决,就是我不太会算时间复杂度和空间复杂度,听说map这两样都挺耗的,毕竟人家这么好用~

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<map>
    using namespace std;
    typedef long long ll;
    const ll maxn=1e6+50;
    
    namespace Fast_IO
    { //orz laofu
        const int MAXL((1 << 18) + 1);int iof, iotp;
        char ioif[MAXL], *ioiS, *ioiT, ioof[MAXL],*iooS=ioof,*iooT=ioof+MAXL-1,ioc,iost[55];
        char Getchar(){
            if (ioiS == ioiT){
                ioiS=ioif;ioiT=ioiS+fread(ioif,1,MAXL,stdin);return (ioiS == ioiT ? EOF : *ioiS++);
            }else return (*ioiS++);
        }
        void Write(){fwrite(ioof,1,iooS-ioof,stdout);iooS=ioof;}
        void Putchar(char x){*iooS++ = x;if (iooS == iooT)Write();}
        inline int read(){
            int x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
    		if(ioc==EOF)exit(0);
            for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
        }
        inline long long read_ll(){
            long long x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
    		if(ioc==EOF)exit(0);
            for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
        }
        template <class Int>void Print(Int x, char ch = ''){
            if(!x)Putchar('0');if(x<0)Putchar('-'),x=-x;while(x)iost[++iotp]=x%10+'0',x/=10;
            while(iotp)Putchar(iost[iotp--]);if (ch)Putchar(ch);
        }
        void Getstr(char *s, int &l){
            for(ioc=Getchar();ioc==' '||ioc=='
    '||ioc=='	';)ioc=Getchar();
    		if(ioc==EOF)exit(0);
            for(l=0;!(ioc==' '||ioc=='
    '||ioc=='	'||ioc==EOF);ioc=Getchar())s[l++]=ioc;s[l] = 0;
        }
        void Putstr(const char *s){for(int i=0,n=strlen(s);i<n;++i)Putchar(s[i]);}
    } // namespace Fast_IO
    using namespace Fast_IO;
    
    ll a[1050][1050];
    
    int main()
    {
    	ll T;
    	T=read_ll();
    	while(T--)
    	{
    		map<ll,map<ll,ll> >mp;
    		ll n,m;
    		n=read_ll();
    		m=read_ll();
    		for(ll i=1;i<=n;i++)
    		{
    			for(ll j=1;j<=m;j++)
    			{
    				a[i][j]=read_ll();
    				mp[i][a[i][j]]++;
    			}
    		}
    		ll sum=0;
    		for(ll i=2;i<=n;i++)
    		{
    			for(auto &j:mp[i])
    			{
    				sum+=min(j.second,mp[i-1][j.first]);
    			}
    		}
    		printf("%lld
    ",sum);
    	}
    }
    

    B.Gym - 102152C 找规律

    传送门

    题意:

    给定n和m,定义(F(n,m)=gcd(5^n+7^n,5^m+7^m))

    (F(n,m)),保证给定的n和m一定互质。

    做法:

    这是个规律题,首先分析,n和m不可能同为偶数。

    当n和m同为奇数时,答案为12,

    否则,答案为2。

    闲话:

    我活生生对着这题看了快一个小时你敢信,其实我中间有想到奇偶规律。我一开始就是觉得他是有规律的,所以写了个暴力程序跑,然后大概是n和m太大就炸掉了,所以蒙蔽了我的双眼,让我成功错过了正确答案,最后忍不住去看了题解。发现是我**了。感觉做题的一个规律就是,注意观察其他人的过题时间,运行时间以及内存来推算自己的做法,虽然现场赛好像是看不到这些的~

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<map>
    using namespace std;
    typedef long long ll;
    const ll maxn=1e6+50;
    
    namespace Fast_IO
    { //orz laofu
        const int MAXL((1 << 18) + 1);int iof, iotp;
        char ioif[MAXL], *ioiS, *ioiT, ioof[MAXL],*iooS=ioof,*iooT=ioof+MAXL-1,ioc,iost[55];
        char Getchar(){
            if (ioiS == ioiT){
                ioiS=ioif;ioiT=ioiS+fread(ioif,1,MAXL,stdin);return (ioiS == ioiT ? EOF : *ioiS++);
            }else return (*ioiS++);
        }
        void Write(){fwrite(ioof,1,iooS-ioof,stdout);iooS=ioof;}
        void Putchar(char x){*iooS++ = x;if (iooS == iooT)Write();}
        inline int read(){
            int x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
    		if(ioc==EOF)exit(0);
            for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
        }
        inline long long read_ll(){
            long long x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
    		if(ioc==EOF)exit(0);
            for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
        }
        template <class Int>void Print(Int x, char ch = ''){
            if(!x)Putchar('0');if(x<0)Putchar('-'),x=-x;while(x)iost[++iotp]=x%10+'0',x/=10;
            while(iotp)Putchar(iost[iotp--]);if (ch)Putchar(ch);
        }
        void Getstr(char *s, int &l){
            for(ioc=Getchar();ioc==' '||ioc=='
    '||ioc=='	';)ioc=Getchar();
    		if(ioc==EOF)exit(0);
            for(l=0;!(ioc==' '||ioc=='
    '||ioc=='	'||ioc==EOF);ioc=Getchar())s[l++]=ioc;s[l] = 0;
        }
        void Putstr(const char *s){for(int i=0,n=strlen(s);i<n;++i)Putchar(s[i]);}
    } // namespace Fast_IO
    using namespace Fast_IO;
    
    ll a[1050][1050];
    
    ll qpow(ll a,ll b)
    {
    	ll ans=1;
    	ll base=a;
    	while(b)
    	{
    		if(b&1)ans=ans*base;
    		base*=base;
    		b>>=1;
    	}
    	return ans;
    }
    
    bool isPrime_3(int n)
    {
    	if(n==2||n==3)	return 1;
    	if(n%6!=1&&n%6!=5)	return 0;
    	for(int i=5;i<=floor(sqrt(n));i+=6)
    		if(n%i==0||n%(i+2)==0)	return 0;
    	return 1;
    }
    
    
    int main()
    {
    	ll T;
    	T=read_ll();
    	while(T--)
    	{
    		ll n,m;
    		n=read_ll();
    		m=read_ll();
    		if(n%2&&m%2)printf("12
    ");
    		else printf("2
    ");
    	}
    }
    

    C.Gym - 102152I 分类讨论

    传送门

    题意:

    有一个长度为n序列,定义取反操作为将某一个位置上的数变为它的相反数,n和k范围都是1e4,问进行k次取反操作后序列和的最大值,序列里的数字范围是 -1e4~1e4。

    做法:

    正宗分类讨论,但是你得心细。

    首先统计一下序列里负数的个数fu。

    把整个序列按从小到大排序。

    1.如果fu>=k,则把最小的k个数取反,即把绝对值最大的一批负数取反以获得最大的收益。

    2.如果fu<k,则说明对负数取反完后还会剩下一些取反操作,如果这些取反操作用在正数上则会导致最大值减小。

    想到的解决办法是:

    ①如果序列里有0,则非常简单,把剩下的取反操作全部用在0上即可获得最大答案。

    ②如果序列里无0,则需把目前取反后的序列重新从小到大排序,取最小的元素,把剩下的所有取反次数都用在它身上。如果剩余次数为奇数,则最小的这个数会被取反(就算这样损失也是最小的),如果是偶数则不会发生改变。

    其实①②这两种分类讨论可以合并成一个操作做,就先排序,再取出最小的,因为如果有0在的话,那0一定是最小的(因为在这个情况下,负数已经被全部取反了)。

    闲话:

    这道题我一开始太单纯了,纯粹地以为排个序,把前k个取反就好了,结果后来发现可以不停地取反同一个位置。负数当然是能取反多少就取反多少,正数则是能不取反就不取反,零可以用来消耗取反次数。

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const ll maxn=1e6+50;
    
    
    namespace Fast_IO
    { //orz laofu
        const int MAXL((1 << 18) + 1);int iof, iotp;
        char ioif[MAXL], *ioiS, *ioiT, ioof[MAXL],*iooS=ioof,*iooT=ioof+MAXL-1,ioc,iost[55];
        char Getchar(){
            if (ioiS == ioiT){
                ioiS=ioif;ioiT=ioiS+fread(ioif,1,MAXL,stdin);return (ioiS == ioiT ? EOF : *ioiS++);
            }else return (*ioiS++);
        }
        void Write(){fwrite(ioof,1,iooS-ioof,stdout);iooS=ioof;}
        void Putchar(char x){*iooS++ = x;if (iooS == iooT)Write();}
        inline int read(){
            int x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
    		if(ioc==EOF)exit(0);
            for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
        }
        inline long long read_ll(){
            long long x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
    		if(ioc==EOF)exit(0);
            for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
        }
        template <class Int>void Print(Int x, char ch = ''){
            if(!x)Putchar('0');if(x<0)Putchar('-'),x=-x;while(x)iost[++iotp]=x%10+'0',x/=10;
            while(iotp)Putchar(iost[iotp--]);if (ch)Putchar(ch);
        }
        void Getstr(char *s, int &l){
            for(ioc=Getchar();ioc==' '||ioc=='
    '||ioc=='	';)ioc=Getchar();
    		if(ioc==EOF)exit(0);
            for(l=0;!(ioc==' '||ioc=='
    '||ioc=='	'||ioc==EOF);ioc=Getchar())s[l++]=ioc;s[l] = 0;
        }
        void Putstr(const char *s){for(int i=0,n=strlen(s);i<n;++i)Putchar(s[i]);}
    } // namespace Fast_IO
    using namespace Fast_IO;
    ll a[maxn];
    int main()
    {
    	ll T;
    	T=read_ll();
    	while(T--)
    	{
    		ll n,k,fu=0,ling=0,sum=0;
    		n=read_ll();
    		k=read_ll();
    		for(ll i=1;i<=n;i++){
    			a[i]=read_ll();
    			if(a[i]<0)fu++;
    			else if(a[i]==0)ling++;
    		}
    		sort(a+1,a+1+n);
    		if(fu<k)
    			if(ling)
    				for(ll i=1;i<=n;i++)
    					if(a[i]<0)sum+=-a[i];
    					else sum+=a[i];
    			else
    			{
    				for(ll i=1;i<=n;i++){
    					if(a[i]>=0)break;
    					a[i]=-a[i];
    				}
    				sort(a+1,a+1+n);
    				if((k-fu)%2)sum+=-a[1];
    				else sum+=a[1];
    				for(ll i=2;i<=n;i++)sum+=a[i];
    			}	
    		else
    			for(ll i=1;i<=n;i++)
    				if(i<=k)sum+=-a[i];
    				else sum+=a[i];
    		printf("%lld
    ",sum);
    	}
    }
    

    大大大闲话

    虽然昨晚上第一场小赛我缺席了,但是今天我补上啦~,虽然还是菜菜的,但是看着一个队都是绿的真开心!冲冲冲!

  • 相关阅读:
    Python:virtualenv 和 venv
    NHibernate从入门到精通系列(9)——一对多关联映射
    开源框架完美组合之Spring.NET + NHibernate + ASP.NET MVC + jQuery + easyUI 中英文双语言小型企业网站Demo
    Android与IIS身份验证——基本验证
    NHibernate从入门到精通系列(8)——一对一关联映射
    NHibernate从入门到精通系列(10)——多对多关联映射
    Android与IIS身份验证——Form验证
    以C#编写的Socket服务器的Android手机聊天室Demo
    【算法系列】使用LINQ来检测和删除重复的文件
    【算法系列】一道笔试试题——回文数算法
  • 原文地址:https://www.cnblogs.com/wuanran/p/13373705.html
Copyright © 2011-2022 走看看