0%

题目大意

题目描述
给定二维平面上的一个标准椭圆方程:

x2a2+y2b2=1\frac{x^2}{a^2} + \frac{y^2}{b^2} = 1

其中 aabb 是正实数,分别代表椭圆的半轴。

同时给定平面上的一条直线方程:

y=kx+c y = kx + c

已知该直线一定会将椭圆分割成两个区域,要求计算并输出这两个区域中面积较大的那一部分的面积。

输入格式
第一行包含两个整数 aabb1a,b1031 \le a,b \le 10^3),表示椭圆的两个半轴长。
第二行包含两个整数 kkcck,c103|k|,|c| \le 10^3),定义了直线 y=kx+cy = kx + c
数据保证直线必定与椭圆相交于两个不同的点。

输出格式
输出一个浮点数,表示椭圆中面积较大那一部分的面积。
你的答案与标准答案的绝对误差或相对误差不超过 10610^{-6} 即被视为正确。

样例

输入

1
2
2 3
1 1

输出

1
12.709803500

样例解释
在样例中,给定椭圆方程为 x222+y232=1\frac{x^2}{2^2} + \frac{y^2}{3^2} = 1,即 x24+y29=1\frac{x^2}{4} + \frac{y^2}{9} = 1
给定直线方程为 y=x+1y = x + 1
整个椭圆的面积为 π×a×b=6π18.8495559\pi \times a \times b = 6\pi \approx 18.8495559
直线 y=x+1y = x + 1 穿过该椭圆将其分成两部分,经过计算,这两部分中面积较大的区域面积约为 12.70980350012.709803500

思路讲解

椭圆方程 x2a2+y2b2=1\frac{x^2}{a^2} + \frac{y^2}{b^2} = 1,做代换 u=xa,  v=ybu = \frac{x}{a},\; v = \frac{y}{b},椭圆变成 u2+v2=1u^2 + v^2 = 1(单位圆)。

直线 y=kx+cy = kx + c 变成 bv=kau+cbv = ka \cdot u + c,即 v=kabu+cbv = \frac{ka}{b}\,u + \frac{c}{b}

面积缩放关系:这个变换的雅可比行列式是 abab,所以在 (u,v)(u,v) 平面上算出的面积,乘以 abab 就是椭圆上的面积

具体而言,雅克比行列式是:

u=xa,v=ybu = \frac{x}{a}, \quad v = \frac{y}{b}

反过来就是 x=au,  y=bvx = au,\; y = bv。雅可比矩阵是把所有偏导数摆成矩阵:

J=(xuxvyuyv)=(a00b)J = \begin{pmatrix} \frac{\partial x}{\partial u} & \frac{\partial x}{\partial v} \\ \frac{\partial y}{\partial u} & \frac{\partial y}{\partial v} \end{pmatrix} = \begin{pmatrix} a & 0 \\ 0 & b \end{pmatrix}

雅可比行列式 = det(J)=ab0=ab\det(J) = ab - 0 = ab

这意味着:(u,v)(u,v) 平面上任何一块面积为 SS 的区域,对应回 (x,y)(x,y) 平面上面积为 abSab \cdot S

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void Solve() {
ll a0, b0, k0, c0;
cin >> a0 >> b0 >> k0 >> c0;
DB k1 = (DB) (k0 * a0) / b0;
DB c1 = c0 / DB(b0);
DB dis = distancePL(Point(0, 0), Line(k1, c1));
cout << fsp(10);
// 这个 dis = 0 的特判其实不需要
if (dis == 0) {
DB area = pi * a0 * b0;
area /= 2;
cout << area << "\n";
return;
}
// 弦长
DB xian = 2 * sqrt(1 - dis * dis);
// 角度大小
DB angle = 2 * acos(dis / 1);
DB shan = (angle / (2 * pi)) * pi;
DB area = shan - 0.5 * dis * xian;

area *= a0;
area *= b0;
area = max(area, pi * a0 * b0 - area);

cout << area << "\n";
}

AC代码

AC
https://codeforces.com/gym/106139/submission/367303278

心路历程(WA,TLE,MLE……)

这个形式一定要化简到 v=u。。。什么的形式

image

题目大意

题目描述
对于一个严格大于 0 的正整数 xx,按以下过程构造字符串 S(x)S(x)

  1. 初始字符串为空。

  2. xx 的十进制表示(无前导零)追加到字符串右侧。

  3. 如果 x9x \le 9,过程结束;否则,将 xx 替换为其各位数字之和,并返回步骤 2 继续执行。

例如:

  • S(75)S(75) 为 “75123”(75 的数位和为 12,12 的数位和为 3,依次拼接为 75 + 12 + 3 = 75123)。

  • S(30)S(30) 为 “303”(30 的数位和为 3,拼接为 30 + 3 = 303)。

  • S(9)S(9) 为 “9”。

现在给定一个由数字组成的字符串 ss,要求重新排列该字符串中的所有字符,使其能够构成某个正整数 xx 对应的生成字符串 S(x)S(x)。不允许添加或删除字符。如果给定的 ss 已经是合法的 S(x)S(x),可以保持不变。数据保证一定存在至少一种合法的排列方式。

输入格式
第一行包含一个整数 tt1t1041 \le t \le 10^4),表示测试用例的数量。
每个测试用例包含一行数字字符串 ss1s1051 \le |s| \le 10^5)。
所有测试用例中 s|s| 的总和不超过 10510^5

输出格式
对于每个测试用例,输出重排后的字符串。如果有多个合法答案,输出其中任意一个即可。

样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Input:
5
12735
1
011
99999299999999299959999999999999
4621467

Output:
75123
1
101
99999999999999999999999999992529
6442167

样例解释

  • 第一个样例 12735:重排为 75123,对应 x=75x = 75 的生成结果(75 -> 12 -> 3)。

  • 第二个样例 1:重排为 1,对应 x=1x = 1 的生成结果。

  • 第三个样例 011:重排为 101,对应 x=10x = 10 的生成结果(10 -> 1)。

思路讲解

首先,对于重排问题,原来的顺序是一点用都没有的,我们只考虑原来的个数!也就是 freq 统计一手频数

image

说白了就是,字符串的最后一位数状态很少,但是光枚举那个东西想反推出来一整个答案,难如登天。

说白了,一个东西的状态少,不一定就是去枚举他,因为枚举的越少,难度一般来说越大。所以说,我们一般要枚举的是不多不少的东西

因此,这个不多不少的东西,是什么呢?结合这个不太好反向思考的这个特性,我们发现,可以枚举第一部分的这个数位和。枚举了第一部分的数位和以后,你会发现,后面的东西全部都定下来了。那后面的东西都定下来了,确定是否能够取得第一部分的这个数位和,是不是也是非常 easy 的呢?

image

实现上来说:(还是用这个 while condition 写法比较好)

1
2
3
4
5
6
ll d=sum;
while (d>9) {
ans+=to_string(d);
d=count_digit(d);
}
ans+=to_string(d);

AC代码

AC
https://codeforces.com/contest/2204/submission/367073785

心路历程(WA,TLE,MLE……)

题目大意

题目总结

给定一个无向图(无重边、无自环),你要给每条边指定一个方向,得到有向图。

定义一条点序列 v1,v2,,vkv_1,v_2,\dots,v_k(长度可任意大,点可重复)是“交替路径”,当且仅当相邻边方向按如下模式交替:

  • 第 1 条边是 v1v2v_1 \to v_2

  • 第 2 条边是 v3v2v_3 \to v_2

  • 第 3 条边是 v3v4v_3 \to v_4

  • 第 4 条边是 v5v4v_5 \to v_4

  • 之后继续这样“顺、逆、顺、逆”交替。

一个点 vv 被称为“beautiful”,如果在原图中所有从 vv 出发的路径(不要求简单路径,允许重复点和边)在你定向后都满足上面的交替性质。

目标:对每个测试用例,求最多能让多少个点成为 beautiful。


输入输出要求(题意层面)

  • 输入有多组测试。

  • 每组给 n,mn,mmm 条无向边。

  • 需要输出一个整数:该组图中可成为 beautiful 的点数最大值。


样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Input
4
8 9
1 3
1 4
2 3
2 4
5 6
6 7
7 8
8 5
6 8
4 0
6 2
1 5
2 3
1 0
1
2
3
4
5
Output
2
4
4
1

样例解释

  • 第 1 组输出 2:最多只能让 2 个点满足“从该点出发的任意路径都交替”。

  • 第 2 组输出 4:图中没有边,任意从点出发的路径都平凡成立,所以 4 个点都可 beautiful。

  • 第 3 组输出 4:最多可让 4 个点满足条件。

  • 第 4 组输出 1:只有 1 个点且无边,因此这个点可 beautiful。

思路讲解

image

不难发现,有奇数环的环,搞出来一个这个矛盾的方案是非常容易的。

image

当然,这个是反向论证,我们再正向论证一下,为什么我们一定要求这张图是一个二分图。不难发现,一张图上,一个点要么其所有的边都是出去的,要么所有边都是进去的。

image

你说你如果违反这一要求会怎么样?那么就会一定不符合这个题设要求(这个应该是非常显然的,因为这样子会导致一个 a→b→c 序列,但是题设要求是 a→b<-c)。

image

AC代码

心路历程(WA,TLE,MLE……)

题目大意

题目总结:

给定一个长度为 n 的数组 a

对任意区间 [l, r],定义其权值为:

w=i=lrj=lr(aiaj) w=\sum_{i=l}^{r}\sum_{j=l}^{r}(a_i \oplus a_j)

其中 表示按位异或。

要求你计算数组中所有非空子区间的权值之和,并对 10^9+7 取模后输出。

输入范围为:

  • 1 ≤ n ≤ 2×10^5

  • 0 ≤ a_i ≤ 10^6

输出一个整数,表示最终答案。

样例:

1
2
3
4
5
6
输入:
6
1 1 4 5 1 4

输出:
422

样例含义:对数组 [1,1,4,5,1,4] 的所有非空子区间分别计算上述双重异或和权值,再把这些权值全部累加,最终结果为 422

思路讲解

注意,题目中的是非有序对双重求和,所以结果不要忘记乘以一个 2。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
vector<vector<ll>> suf_bits(N+2,vector<ll>(26));
vector<vector<ll>> suf_nobits(N+2,vector<ll>(26));
for (ll i=N;i>=1;--i) {
for (int j=0;j<25;++j) {
// 注意,我们这里写的是(N-i+1),是指的包含 i 的可以选择的右端点数量
suf_bits[i][j]=suf_bits[i+1][j]+(A[i]>>j&1)*(N-i+1);
// (A[i]>>j&1)^1,不要偷懒,不加这个 &1,一定要有 &1 才对
suf_nobits[i][j]=suf_nobits[i+1][j]+((A[i]>>j&1)^1)*(N-i+1);
}
}
ll ans=0;
for (int i=1;i<=N;++i) {
for (int j=0;j<25;++j) {
if (A[i]>>j&1) {
ll suf=suf_nobits[i+1][j];
ll lans=suf%mod*i%mod;
lans*=(1ll<<j);
lans%=mod;
ans+=lans*2;
ans%=mod;
}else {
ll suf=suf_bits[i+1][j];
ll lans=suf%mod*i%mod;
lans*=(1ll<<j);
lans%=mod;
ans+=lans*2;
ans%=mod;
}
}
}

AC代码

AC
http://10.199.227.101/contest/1005/problem/L3-1/submission-detail/2157

心路历程(WA,TLE,MLE……)