NowcoderWannafly挑战赛25游记(A~D)

A-因子
p ≤ 10000 p\leq 10000 p10000说明 p p p分解质因数后各个质因子的个数不会很多
只需要考虑 n ! n! n! p p p的每一个质因子的个数
最后 a n s = m i n ( ⌊ a l l n u m ⌋ ) ans=min(\lfloor \frac{all}{num} \rfloor) ans=min(numall)( a l l all all表示 p p p的某个质因子在 n ! n! n!中的个数, n u m num num表示 p p p中含几个该质因子)
a l l all all很好求,具体见代码,还有就是注意别乘爆long long

#include <cstdio>
#include <algorithm>
#define INF 0x3f3f3f3f3f3f3f3f
#define M 10

typedef long long LL;
struct Data{
	int val, num;
}qu[M];

using namespace std;
int main() {
	LL n;
	int p, cnt = 0;
	scanf("%lld%d", &n, &p);
	int x = 1;
	while (p > 1) {
		x++;
		if (p % x == 0) {
			qu[++cnt].val = x;
			while (p % x == 0) {
				p /= x;
				qu[cnt].num++;
			}
		}
	}
	LL ans = INF;
	for (int i = 1; i <= cnt; ++i) {
		LL nn = n, all = 0;
		while (nn > 0) {//求all
			all += nn / qu[i].val;
			nn /= qu[i].val;
		}
		ans = min(all / qu[i].num, ans);
	}
	printf("%lld\n", ans);
	return 0;
} 

B-面积并
分三种情况讨论:

  1. 圆在正多边形外( r &gt; l r&gt;l r>l),面积并为圆的面积
    a n s = π r 2 ans=\pi r^2 ans=πr2
  2. 圆在正多边形内( r &lt; c u r&lt;cu r<cu)( c u cu cu是乱打的别在意(铜真香),具体见 3 3 3中的图)
    就是分成 n n n小块
    a n s = n × l 2 × s i n ( 2 π n ) 2 ans=n\times \frac{l^2\times sin(\frac{2\pi}{n})}{2} ans=n×2l2×sin(n2π)
  3. 有圆从正多边形里面突出来了!
    xxx
    就要把正多边形分成 n n n份,每份如上图,由一个扇形和两个三角形组成
    d = C D = r 2 − c u 2 d=CD=\sqrt{r^2-cu^2} d=CD=r2cu2
    a n s = n ( S s e c t o r + S t r i a n g l e ) = n ( 2 sin ⁡ − 1 ( d r ) 2 π × π r 2 + 1 2 l 2 sin ⁡ ( 2 π n ) − d × c u ) ans=n(S_{sector}+S_{triangle})=n(\frac{2\sin^{-1}(\frac{d}{r})}{2\pi}\times\pi r^2+\frac{1}{2}l^2\sin(\frac{2\pi}{n})-d\times cu) ans=n(Ssector+Striangle)=n(2π2sin1(rd)×πr2+21l2sin(n2π)d×cu)
    还有要注意的是精度问题,要用long double代替double
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <math.h>

using namespace std;
const long double pi = 3.1415926535897932384626434;

int main() {
	long long n, l, r;
	scanf("%lld%lld%lld", &n, &l, &r);
	long double cu = cos(pi / n) * l;
	if (r < cu) {
		long double ans = l * l * sin(pi / n * 2) / 2 * n;
		cout << fixed << setprecision(2) << ans;
		return 0;
	}
	if (r > l) {
		 long double ans = r * r * pi;
		cout << fixed << setprecision(2) << ans;
		return 0;
	}
	double d = sqrt(r * r - cu * cu);
	double ans = n * (l * l * sin(pi / n * 2) / 2 - d * cu + r * r * asin(d / r));
	cout << fixed << setprecision(2) << ans;
	return 0;
}

C-期望操作数
纯板子…但是逆元操作太毒瘤
对于逆元的操作和前几天牛客网NOIP赛前集训营-提高组(第三场)A-管道维修其实是差不多的
就是要求 1 1 1 n n n的逆元有点费时间(如果用 θ ( n l o g 2 n ) \theta(nlog_2n) θ(nlog2n)求显然会T)
下面引入 θ ( n ) \theta(n) θ(n)预处理 1 1 1 n n n逆元的方法(其实根据逆元的意义很好推的)

	ny[1] = 1;
	for (int i = 2; i < N; ++i) {
		ny[i] = ny[MOD % i] * (MOD - MOD / i) % MOD;
	}

公式还是再推一遍吧
f ( 0 ) = 0 , f ( n ) = ∑ i = 0 n f ( i ) n + 1 + 1 f(0)=0,f(n)=\frac{\sum_{i=0}^{n}f(i)}{n+1}+1 f(0)=0,f(n)=n+1i=0nf(i)+1
化简后 f ( 0 ) = 0 , f ( n ) = ∑ i = 0 n − 1 + n + 1 n f(0)=0,f(n)=\frac{\sum_{i=0}^{n-1}+n+1}{n} f(0)=0,f(n)=ni=0n1+n+1

#include <cstdio>
#define MOD 998244353
#define N 10000005

typedef long long LL;
using namespace std;

LL ny[N], dp[N];
int main() {
	int t;
	scanf("%d", &t);
	ny[1] = 1;
	for (int i = 2; i < N; ++i) {
		ny[i] = ny[MOD % i] * (MOD - MOD / i) % MOD;
	}
	dp[0] = 0;
	int pre = 0;	
	for (int i = 1; i < N; ++i) {
		dp[i] = (pre + i + 1) * ny[i] % MOD;
		pre = (pre + dp[i]) % MOD;
	}
	while (t--) {
		int x, q;
		scanf("%d%d", &x, &q);
		printf("%lld\n", dp[q - x]);
	}
	return 0;
}

D-玩游戏
先上图
yyy

因为每个顶点入度 ≤ 2 \leq2 2,所以图一定是长这样差不多的
考虑到必输态是 1 1 1 n n n的每一条边的都是权值为 1 1 1的桥,也就是一条链,但每个人每次只能将权值减一,说明该链的长度是至关重要的。如果jxc想赢,刚开始所有的w的和为奇数,那么他一定要使剩下的最后一条链的为偶数,他要在nqiiii把偶数的链拆完之前把奇数的链拆完,反之亦然。
拆掉一条链需要花费的代价是 m i n ( w − o n − t h e − l i n k ) min(w-on-the-link) min(wonthelink)
因为 1 1 1 n n n的链条数是确定的,长度也是确定的,所以可以把这些链分成长度为奇数偶数两种,再把所有同种类的代价相加,算出ta[0]ta[1],然后在比大小就行了。
ps:这道又要开long long…又被坑了…

#include <cstdio>
#include <algorithm>
#define INF 0x3f3f3f3f
#define N 100010

using namespace std;

struct Data{
	int to, len;
}e1[N], e[N][3], en[N];
int cnt1, cnt[N], cntn, n, m, vis[N];
long long ta[2];

inline void add(int x, int y, int z) {
	if (x == 1) {
		e1[++cnt1].to = y;
		e1[cnt1].len = z;
	}
	else
	if (x == n) {
		en[++cntn].to = y;
		en[cntn].len = z;
	}
	else {
		e[x][++cnt[x]].to = y;
		e[x][cnt[x]].len = z;
	}
}

void dfs(int x, int mini, int od) {
	if (x == n) {
		ta[od] += (long long)mini;
		return;
	}
	vis[x] = 1;
	if (x == 1) {
		for (int i = 1; i <= cnt1; ++i) {
			dfs(e1[i].to, min(mini, e1[i].len), 1 - od);
		}
	}
	for (int i = 1; i <= cnt[x]; ++i) {
		if (!vis[e[x][i].to]) {
			dfs(e[x][i].to, min(mini, e[x][i].len), 1 - od);
		}
	}
}

int main() {
	scanf("%d%d", &n, &m);
	int all = 0;
	for (int i = 1; i <= m; ++i) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		add(u, v, w);
		add(v, u, w);
		all += w % 2;
	}
	dfs(1, INF, 0);
	all %= 2;
	if (all) {
		if (ta[1] <= ta[0]) puts("Yes");
		else puts("No");
	}
	else {
		if (ta[0] <= ta[1]) puts("Yes");
		else puts("No");
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值