AutoX安途杯中山大學程序設計校賽(同步賽)題解


 賽時過題:A C D I

賽后補題:B E G

A:

題意:給定兩個數A,B求一個C,要求三個數之和是1e6的倍數,三個數字的范圍都是[0, 1e6)

解題思路:首先我們要知道一個數字0倍也是它的倍數,那么如果A,B都是0的時候,C是0也可以滿足;但是如果A,B不是0的時候,我們可以先用1e6去減,如果C小於0的話再添加一個1e6

 

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int T;
int A,B,C;
int main()
{
	cin >> T;
	while(T--)
	{
		cin >> A >> B;
		C = 1000000 - A - B;
		if(C < 0) C = 2000000 - A - B;
		if(C == 1000000) C = 0;
		cout << C<<"\n";
	}
	return 0;
}

C:

題目大意:給定一個3 * 3的矩陣,給定固定位置的三個數字,求是否能推出整個矩陣

解題思路:隊友寫的,通過推導方式可以求出若(6 * a + 3 * b + 3 * d) % 4不為0的時候,矩陣不存在,那么反之則存在

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <cctype>
#include <iostream>
#include <fstream>
#include <limits.h>
#include <algorithm>
#include <sstream>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <cstdio>
#include <list>
#define RE0 return 0;
#define pi acos(-1.0)
#define pii pair<int, int>
#define ll long long
const long long mod = (ll)(1e7 + 1e5 + 1e3 + 7);
const double eps = 1e-8;
const int inf = 0x3f3f3f3f;
const int maxN = (int)1e6 + 7;
const int modulenumber = (int)1e9 + 7;
using namespace std;
ofstream ofs;

typedef struct stu
{
	int number;
	char name[35];
	int time;
	int happy;
	bool friend operator <(stu a, stu b)
	{
		return a.happy < b.happy;
	}
}  STU;
int cmp(const void* p, const void* q)
{
	int pa = *((int*)p);
	int qa = *((int*)q);
	return qa - pa;
}
long long qpow(long long a, long long b)
{
	long long res = 1;
	while (b)
	{
		if (b & 1)
		{
			res *= a;
			res %= mod;
		}
		b >>= 1;
		a *= a;
		a %= mod;
	}
	return res;
}
int gcd(int a, int b)
{
	return b ? gcd(b, a % b) : a;
}
int Manhattan_distance(int x1, int x2, int y1, int y2)
{
	return max(x1 - x2, x2 - x1) + max(y1 - y2, y2 - y1);
}
inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch>'9')
	{
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
		x = x * 10 + ch - '0', ch = getchar();
	return x * f;
}

map< int, int> cnt;
stack<int> st;
queue<int> que;
multiset<int> se;
string str;

int n, k, T, m;
int flag = 1;

int main()
{
	scanf("%d", &T);
	while (T--)
	{
		int a, b, c, d, e, f, g, h, i;
		scanf("%d%d%d", &a, &b, &d);
		if ((6 * a + 3 * b + 3 * d) % 4)
		{
			printf("-1\n");
		}
		else
		{
			int t = (6 * a + 3 * b + 3 * d) / 4;
			c = t - a - b;
			e = 2 * a + b + d - t;
			f = 2 * t - 2 * a - b - 2 * d;
			g = t - a - d;
			h = 2 * t - 2 * a - 2 * b - d;
			i = 3 * a + 2 * b + 2 * d - 2 * t;
			printf("%d %d %d %d %d %d\n", c, e, f, g, h, i);
		}
	}
	RE0
}

D

題目大意:給定一個含有x的二階行列式,求出x的范圍

解題思路:首先我們要先想到x系數是0的情況,對此拿出來進行討論分析式子是否恆定滿足;再者我們根據樣例分析了負號是在分子上面的,因此我們也需要對系數和被除數進行一個處理;最后不要忘記對分子分母同時取一個最大公因式化簡成最簡形式

#define _CRTSECURE_nOWARnInGS
#pragma warning(disable:4996)
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <list>
using namespace std;

int t;
char s[10];
int n[10];
int pin;

int main()
{
	scanf("%d", &t);
	while (t--)
	{
		memset(n, 0, sizeof(n));
		for (int i = 1; i <= 4; i++)
		{
			int neg = 1;
			memset(s, 0, sizeof(s));
			scanf("%s", s);
			int l = strlen(s);
			if (s[0] == 'x')
			{
				pin = i;
				n[pin] = 1;
			}
			else
			{
				if (s[0] == '-') neg = -1;
				else n[i] = n[i] * 10 + s[0] - '0';
				for (int j = 1; j < l; j++)
				{
					n[i] = n[i] * 10 + s[j] - '0';
				}
				n[i] *= neg;
			}
		}
//		for(int i = 1;i <= 4;++i)
//		{
//			printf("%d ",n[i]);
//		}
//		printf("\n");
		int fmul = n[1] * n[4];
		int smul = n[2] * n[3];
		int pmul;
		int flag = 1;
		int sum = fmul + smul;
		if(pin == 1 || pin == 4)
		{
			pmul = fmul;
		}
		else pmul = smul;
		if(pmul == 0)
		{
			if(fmul > smul) printf("R\n");
			else printf("E\n");
		}
		else
		{
			if(pin == 1 || pin == 4)
			{
				if(fmul > 0)
				{
					flag = 1;
					if(smul < 0) flag = -1;
					if(smul % fmul == 0)
					{
						printf("x>%d\n",smul / fmul);
					}
					else
					{
						printf("x>%d/%d\n",flag * abs(smul / __gcd(smul,fmul)),abs(fmul / __gcd(smul,fmul)));
					}
				}
				else if(fmul < 0)
				{
					if(smul > 0) flag = -1;
					if(smul % fmul == 0)
					{
						printf("x<%d\n",smul / fmul);
					}
					else
					{
						printf("x<%d/%d\n",flag * abs(smul / __gcd(smul,fmul)),abs(fmul / __gcd(smul,fmul)));
					}
				}
			}
			else
			{
				if(smul > 0)
				{
					if(fmul < 0) flag = -1;
					if(fmul % smul == 0)
					{
						printf("x<%d\n",fmul/smul);
					}
					else
					{
						printf("x<%d/%d\n",flag * abs(fmul/__gcd(smul,fmul)),abs(pmul/__gcd(smul,fmul)));
					}
				}
				else
				{
					if(fmul > 0) flag = -1;
					if(fmul % pmul == 0)
					{
						printf("x>%d\n",fmul/pmul);
					}
					else
					{
						printf("x>%d/%d\n",flag * abs(fmul/__gcd(pmul,fmul)),abs(pmul/__gcd(pmul,fmul)));
					}
				}
			}
		}
	}
	return 0;
}

I

題目大意:給定一個數字N,我們需要找出四個數字A,B,C,D使得A * D = B * C,同時N−3sqrt(N)​<A<B<C<D<N

解題思路:我們有一個式子對於任意的(kx * (k + 1)y) = (ky * (k + 1) x)(y = x + 1)

然后我們需要找一個最大倍數K

找的過程中可以用minpos / sqrt(n)去尋找

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
int T;
ll n;
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%lld",&n);
		ld minpos = n - 3 * sqrtl(n);
		ll ans1 = sqrtl(n);
		ll ans2 = ans1+1;
		ll t = minpos / ans1;
		while(minpos >= ans1 * t)
		{
			++t;
		}
		printf("%lld %lld %lld %lld\n",ans1 * t, ans2 * t,ans1 * (t + 1), ans2 * (t + 1));
	}
	return 0;
}

E

題目大意:刪除相鄰的兩個數字,同時補入一個數字是他們兩個相減之后再取絕對值最后獲得一個最小的數字

解題思路:因為數據范圍很小,對於任意位置上面的數字都有兩種可能,第一種是我這個位置上面的數字去減別的數字;第二種是別人來減我這個數字,對於第一種我們直接扔正數的值進去,對於第二種負數的情況我們直接扔負數的數值進去,因為數值很小,我們直接進行DFS就可以解決這個問題

后續思考:在賽時沒有做出來的原因是因為沒有在根據這個數字范圍進行進一步的聯想,沒有進行一個直接的暴力,在過題人數很多的情況下我需要考慮一發很暴力的暴力

#include <bits/stdc++.h>
using namespace std;
int T;
int n,m;
int a[20];
int ans;
void dfs(int val,int id)
{
	if(id > n)
	{
		ans = min(ans,val);
		return;
	}
	dfs(abs(val + a[id]),id + 1);
	dfs(abs(val - a[id]),id + 1);
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i = 1;i <= n;++i) scanf("%d",&a[i]);
		ans = 0x3f3f3f3f;
		dfs(a[1],2);
		printf("%d\n",ans);
	}
	return 0;
}

B:

題目大意:

有一個N * N 的矩陣,我每次可以對這個矩陣進行如下操作:

1:讓整個行開/關 2:讓整個列開/關 3:讓一個對角線開或關

解題思路:

首先我們先不考慮對角線的操作,我們先考慮行和列的操作

如果我們打開一行一列,那么實際上打開的燈的數量是 2 n - 2

根據這個我們推導出式子:n * numr + n * numc - 2 * numr * numc

再根據這個式子,我們思考如果有對角線的情況怎么辦?

那么我們需要記錄對角線等已經點亮了的情況,然后再在后面進行一個相減的操作

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <math.h>
#include <cmath>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <cctype>
#include <iostream>
#include <fstream>
#include <limits.h>
#include <algorithm>
#include <sstream>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <cstdio>
#include <list>
#define RE0 return 0;
#define pi acos(-1.0)
#define pii pair<int, int>
#define ll long long
const long long mod = (ll)(1e7 + 1e5 + 1e3 + 7);
const double eps = 1e-8;
const int inf = 0x3f3f3f3f;
const int maxN = (int)1e6 + 7;
const int modulenumber = (int)1e9 + 7;
using namespace std;
ofstream ofs;

typedef struct stu
{
	int number;
	char name[35];
	int time;
	int happy;
	bool friend operator <(stu a, stu b)
	{
		return a.happy < b.happy;
	}
}  STU;
int cmp(const void* p, const void* q)
{
	int pa = *((int*)p);
	int qa = *((int*)q);
	return qa - pa;
}
long long qpow(long long a, long long b)
{
	long long res = 1;
	while (b)
	{
		if (b & 1)
		{
			res *= a;
			res %= mod;
		}
		b >>= 1;
		a *= a;
		a %= mod;
	}
	return res;
}
int gcd(int a, int b)
{
	return b ? gcd(b, a % b) : a;
}
int Manhattan_distance(int x1, int x2, int y1, int y2)
{
	return max(x1 - x2, x2 - x1) + max(y1 - y2, y2 - y1);
}
inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch>'9')
	{
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
		x = x * 10 + ch - '0', ch = getchar();
	return x * f;
}

map< int, int> cnt;
stack<int> st;
queue<int> que;
multiset<int> se;
string str;

int n, k, T, m;
int flag = 1;

ll col[100005] = { 0 }, row[100005] = { 0 }, dia = 0, numc = 0, numr = 0, numd = 0;

int main()
{
	scanf("%d", &T);
	while (T--)
	{
		memset(col, 0, sizeof col);
		memset(row, 0, sizeof row);
		dia = 0;
		numc = 0;
		numr = 0;
		numd = 0;
		scanf("%d %d\n", &n, &m);
		for (int i = 0; i < m; ++i)
		{
			char c;
			int t;
			scanf("%c", &c);
			while (c == '\n')
			{
				scanf("%c", &c);
			}
			if (c == 'R')
			{
				scanf("%lld", &t);
				if (row[t] == 0)
				{
					row[t] = 1;
					++numr;
					if (col[t] == 1)
					{
						++numd;
					}
				}
				else
				{
					row[t] = 0;
					--numr;
					if (col[t] == 1)
					{
						--numd;
					}
				}
			}
			if (c == 'C')
			{
				scanf("%lld", &t);
				if (col[t] == 0)
				{
					col[t] = 1;
					++numc;
					if (row[t] == 1)
					{
						++numd;
					}
				}
				else
				{
					col[t] = 0;
					--numc;
					if (row[t] == 1)
					{
						--numd;
					}
				}
			}
			if (c == 'D')
			{
				dia = 1 - dia;
			}
			if (dia == 0)
			{
				printf("%lld\n", n * numr + n * numc - 2 * numr * numc);
			}
			else
			{
				printf("%lld\n", n * numr + n * numc - 2 * numr * numc + n - 2 * (numr + numc - 2 * numd));
			}
		}
	}
	RE0
}

G

題目大意:給定n個數字,給定3個棧,如何操作我們可以使得所有數據在第一個棧中以非遞減的形式存在

解題思路:我們對於給定一些數字可以進行這樣一個操作,按這一個數位中是否是1然后把他放入stack2 或者stack3,因為在這一位上是1的,那么他相對這一位數值上是0的數字就要更大一些,那我們每次都進行這樣的操作,並且按照棧的方式把他扔進原棧中,最后就能夠排序成功,而且我們對於每個數字都是需要離散化的(只需要記錄其相應的數字位置),然后對於每個數字我們最多進行操縱10次,最多肯定不會超過20000次

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
pair<int,int> p[maxn];
int ans[maxn][10];
int a[maxn];
int b[maxn];
int c[maxn];
int na,nb,nc;
int n;
int ansn;
void add(int x,int y)
{
	ans[++ansn][0] = x;
	ans[ansn][1] = y;
}
int main()
{
	scanf("%d",&n);
	for(int i = 1;i <= n;++i)
	{
        scanf("%d",&a[i]);
		p[i] = make_pair(a[i],i);
	}
	sort(p + 1,p + 1 + n);
	for(int i = 1;i <= n;++i) a[p[i].second] = i;
	for(int i = 0;i < 10;++i)
	{
		na = 0;
		nb = 0;
		nc = 0;
		for(int j = n;j >= 1;j--)
		{
			if((a[j] >> i) & 1)
			{
				b[++nb] = a[j];
				add(1,2);
			}
			else
			{
				c[++nc] = a[j];
				add(1,3);
			}
		}
		while(nb)
		{
			a[++na] = b[nb--];
			add(2,1);
		}
		while(nc) 
		{
			a[++na] = c[nc--];
			add(3,1);
		}
	}
	printf("%d\n",ansn);
	for(int i = 1;i <= ansn;++i)
	{
		printf("%d %d\n",ans[i][0],ans[i][1]);
	}
	return 0;
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM