第一次小赛

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 = '\0'){
        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=='\n'||ioc=='\t';)ioc=Getchar();
		if(ioc==EOF)exit(0);
        for(l=0;!(ioc==' '||ioc=='\n'||ioc=='\t'||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\n",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 = '\0'){
        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=='\n'||ioc=='\t';)ioc=Getchar();
		if(ioc==EOF)exit(0);
        for(l=0;!(ioc==' '||ioc=='\n'||ioc=='\t'||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\n");
		else printf("2\n");
	}
}

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 = '\0'){
        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=='\n'||ioc=='\t';)ioc=Getchar();
		if(ioc==EOF)exit(0);
        for(l=0;!(ioc==' '||ioc=='\n'||ioc=='\t'||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\n",sum);
	}
}

大大大闲话

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

posted @ 2020-07-24 18:33  AnranWu  阅读(177)  评论(0编辑  收藏  举报