A-因子
p
≤
10000
p\leq 10000
p≤10000说明
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-面积并
分三种情况讨论:
- 圆在正多边形外(
r
>
l
r>l
r>l),面积并为圆的面积
a n s = π r 2 ans=\pi r^2 ans=πr2 - 圆在正多边形内(
r
<
c
u
r<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π) - 有圆从正多边形里面突出来了!
就要把正多边形分成 n n n份,每份如上图,由一个扇形和两个三角形组成
设 d = C D = r 2 − c u 2 d=CD=\sqrt{r^2-cu^2} d=CD=r2−cu2
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π2sin−1(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+1∑i=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)=n∑i=0n−1+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-玩游戏
先上图
因为每个顶点入度
≤
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(w−on−the−link)
因为
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;
}