牛客小白月赛21

题目分类(解题报告按此顺序编写):
  • 签到题:H
  • 前期题:A、C、F、G、I
  • 中期题:E、J
  • 后期题:D、B

H —— “Happy New Year!”

题解

  • 考点:手速和冷静。

  • 输出题目即可。

AC-Code

#include 
using namespace std;

int main() {
	cout << "\"Happy New Year!\"" << endl;
	return 0;
}

A —— Audio

题解

  • 考点:计算几何基础。

  • 由平方反比定律,发现响度相同时只与距离有关,所以我们只需要求一点,使得该点到三角形三个顶点距离相同,即求三角形的外心。

  • 推导过程即联立任意两边的垂直平分线,求垂直平分线的交点即可。

AC-Code

#include 
using namespace std;

int main() {
	double x1, y1, x2, y2, x3, y3;
	while (cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3) {
		double a = ((y2 - y1) * (y3 * y3 - y1 * y1 + x3 * x3 - x1 * x1) - (y3 - y1) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1)) / (2.0 * ((x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1)));
		double b = ((x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1) - (x3 - x1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1)) / (2.0 * ((y3 - y1) * (x2 - x1) - (y2 - y1) * (x3 - x1)));
		double r2 = (x1 - a) * (x1 - a) + (y1 - b) * (y1 - b);
		printf("%.3f %.3f\n", a, b);
	}
	return 0;
}

C —— Channels

题解

  • 考点:前缀和思想,容斥的思想。

  • 计算 [ 1 , r ] [1,r] [1,r]的答案减去 [ 1 , l − 1 ] [1,l-1] [1,l1]的答案即可,不过需要注意其端点可能在广告的时刻哦!

  • 具体计算方法:即只需要考虑如何计算 [ 1 , x ] [1,x] [1,x]的答案。

AC-Code

#include 
using namespace std;
#define ll long long

ll solve(ll t){
	ll ans = t / 60 * 50;
	ans += ((t % 60) <= 50) ? (t % 60) : 50;
	return ans;
}
int main(){
	ll t1,t2;
	while(cin >> t1 >> t2){
		printf("%lld\n", solve(t2) - solve(t1 - 1));
	}
	return 0;
}

F —— Fool Problem

题解

  • 考点:找规律与公式推导
  • 本地暴力求出答案即可发现,答案只与 i i i的奇偶有关
  • 注意数据范围过大,字符串输入

AC-Code

#include 
using namespace std;

int main() {
	string s;
	while (cin >> s) {
		if ((s[s.length()-1] - '0') & 1)
			cout << -1 << endl;
		else
			cout << 1 << endl;
	}
	return 0;
}

G —— Game


题解

  • 考点:题意转换。

  • 不难发现某一个数字的质因子个数是一定的,计算其质因子个数来探究可分解的步数进行博弈即可。

  • 其实最后只需要考虑质因子个数的奇偶性。

AC-Code

#include 
using namespace std;

bool isPrime(int n) {	//返回1表示判断为质数,0为非质数,在此没有进行输入异常检测
	float n_sqrt;
	if (n == 2 || n == 3) return true;
	if (n % 6 != 1 && n % 6 != 5) return false;
	n_sqrt = floor(sqrt((float)n));
	for (int i = 5; i <= n_sqrt; i += 6) {
		if (n % (i) == 0 | n % (i + 2) == 0) return false;
	}
	return true;
}

int main() {
	int n;
	while (cin >> n) {
		if (isPrime(n)) {
			cout << "Nancy" << endl;
		}
		else {
			int k = 0;
			for (int i = 2; i * i <= n; ++i) {
				if (!(n % i)) {
					++k;
					n /= i;
					--i;
				}
			}
			if (k & 1)
				cout << "Johnson" << endl;
			else
				cout << "Nancy" << endl;
		}
	}
	return 0;
}

I —— I love you

题解

  • 考点:动态规划
  • 牛客小白月赛3的 T 2 T2 T2类似,只不过这里字符串长了一些(记 f i f_i fi表示匹配到 i l o v e y o u iloveyou iloveyou i i i位的方案数,遇到一个字符从其前序字符转移过来即可)牛客小白月赛21_第1张图片

AC-Code

#include 
using namespace std;

int main() {
    string s;
    while (cin >> s) {
        ll ans = 0;
        transform(s.begin(), s.end(), s.begin(), ::tolower); //转换为小写
        ll a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0;
        for (int i = 0; i < s.length(); ++i) {
            if (s[i] == 'i')
                a = (a + 1) % mod;
            if (s[i] == 'l')
                b = (b + a) % mod;
            if (s[i] == 'o')
                c = (c + b) % mod;
            if (s[i] == 'v')
                d = (d + c) % mod;
            if (s[i] == 'e')
                e = (e + d) % mod;
            if (s[i] == 'y')
                f = (f + e) % mod;
            if (s[i] == 'o')
                g = (g + f) % mod;
            if (s[i] == 'u')
                h = (h + g) % mod;
        }
        cout << h << endl;
    }
 
}

E —— Exams

题解

  • 考点:模拟。

  • 按照题目意思计算学分绩即可。

  • 注意题目中提到“计算且仅计算必修和限选课程”,故任选学分不算在学分绩的总学分里面。

AC-Code

#include 
using namespace std;

double xz[64], xf[64], pscj[64], psbl[64], qzcj[64], qzbl[64], qmcj[64], qmbl[64];
int main() {
	int n;
	while (cin >> n) {
		double ans = 0;
		double zxf = 0;
		for (int i = 0; i < n; i++) {
			cin >> xz[i] >> xf[i] >> pscj[i] >> psbl[i] >> qzcj[i] >> qzbl[i] >> qmcj[i] >> qmbl[i];
			if (xz[i] == 2)	continue;
			zxf += xf[i];
		}
		for (int i = 0; i < n; i++) {
			if (xz[i] == 2)	continue;
			int cj = round(pscj[i] * psbl[i] + qzcj[i] * qzbl[i] + qmcj[i] * qmbl[i]);
			ans += cj * xf[i] / zxf;
		}
		printf("%.2f\n", ans);
	}
	return 0;
}


J —— Jelly

题解

  • 考点:Bfs搜索。

  • 三维迷宫?求从(1,1,1)到(n,n,n)的最短路。

  • 搜索的时候一改二维搜索的四连通,改为三维搜索的六连通,上下左右前后6个方向进行Bfs。

AC-Code

#include 
using namespace std;

int n;
int dx[6] = { 0,0,0,0,1,-1 };
int dy[6] = { 0,0,1,-1,0,0 };
int dz[6] = { 1,-1,0,0,0,0 };
char ma[101][101][101];
struct node {
	int x, y, z;
	int val;
	node(int xx, int yy, int zz, int vv) {
		x = xx;
		y = yy;
		z = zz;
		val = vv;
	}
};
bool check(int x, int y, int z) {
	if (x < 1 || x > n || y < 1 || y > n || z < 1 || z > n)
		return false;
	if (ma[x][y][z] == '*')	return false;
	return true;
}
int bfs() {
	queue<node>q;
	q.push(node(1, 1, 1, 1));
	ma[1][1][1] = '*';
	while (!q.empty()) {
		node now = q.front();
		q.pop();
		if (now.x == n && now.y == n && now.z == n) {
			return now.val;
		}
		for (int i = 0; i < 6; ++i) {
			int nx = now.x + dx[i];
			int ny = now.y + dy[i];
			int nz = now.z + dz[i];
			if (check(nx, ny, nz)) {
				q.push(node{ nx, ny, nz, now.val + 1 });
				ma[nx][ny][nz] = '*';
			}
		}
	}
	return -1;
}
int main() {
	while (cin >> n) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				for (int k = 1; k <= n; ++k) {
					cin >> ma[i][j][k];
				}
			}
		}
		cout << bfs() << endl;
	}
	return 0;
}

D —— DDoS

题解

  • 考点:题意转化,拓扑图路径计数

  • 不易观察、挺难发现、较难得到攻击者可以通过调整发送数据包的时间来使得所有数据包同时到达服务器,故原题意转化为求1到n的路径条数,拓扑图上DP即可。

  • 注意定向的含义是规定路线及经过的中继节点,所以重边的时候格外小心(需要算两倍)。

  • 边权无用(其实这里给了个奇怪的数据范围是在暗示呢QwQ)。

AC-Code

#include 
using namespace std;
const int maxn = 2e5;
const int mod = 20010905;

struct Edge {
	int to;
	int next;
}edge[maxn];
int head[maxn];
int cnt = 0;

void add(int u, int v) {
	edge[cnt].to = v;
	edge[cnt].next = head[u];
	head[u] = cnt++;
}
ll f[maxn];
ll dfs(int u) {
	if (f[u])	return f[u];
	ll ans = 0;
	for (int i = head[u]; ~i; i = edge[i].next) {
		int v = edge[i].to;
		ans = (ans + dfs(v)) % mod;
	}
	f[u] = ans;
	return ans;
}
int main() {
	int n, m;
	while (cin >> n >> m) {
		memset(head, -1, sizeof head);
		cnt = 0;
		memset(f, 0, sizeof f);
		f[1] = 1;
		for (int i = 1; i <= m; ++i) {
			int x, y, z;
			cin >> x >> y >> z;
			add(y, x);
		}
		cout << dfs(n) << endl;
	}

	return 0;
}

B —— Bits

题解

  • 考点:模拟,二进制的神奇应用(计算图形学???)

  • 请参看这里,也可以通过Dfs来写,不过注意一下奇偶的位置。

AC-Code

无,不会,太菜了

你可能感兴趣的:(ACM,牛客小白月赛)