A.Pretty Permutations
构造,处理奇数前三个顺序1,2,3->3,1,2
然后搞,反思一下自己把最后一个搬在第一个FastFastWA
着急了代码比较丑但是能看懂凑合看
/*
* @Descripttion:
* @Author: ssw
* @Date: 2021-05-30 04:49:52
* @LastEditors: ssw
* @LastEditTime: 2021-06-25 23:45:35
*/
#include<iostream>
using namespace std;
int n, m;
int main(){
cin >> n;
while(n--)
{
cin >> m;
if(m==2)
{
cout << 2 << ' ' << 1 << endl;
continue;
}
else if (m==3)
{
cout << 3 << ' ' << 1 << ' ' << 2 << endl;
continue;
}
else if(m%2==0)
{
for (int i = 1; i <= m;i+=2)
{
cout << i + 1 << ' ' << i << ' ';
}
cout << endl;
continue;
}
else
{
cout << 3 << ' ' << 1 << ' ' << 2 << ' ';
for (int i = 4; i <= m;i+=2)
{
cout << i + 1 << ' ' << i << ' ';
}
cout << endl;
continue;
}
}
return 0;
}
B.Pleasant Pairs
找见符合的
(
i
,
j
)
(i,j)
(i,j)使得
a
i
∗
a
j
=
=
i
+
j
&
i
<
j
\quad a_i*a_j==i+j \quad\& \quad i<j
ai∗aj==i+j&i<j
化简一下式子根据已经有的
i
i
i跳着找
j
j
j速度会快一丢丢
a
j
=
i
+
j
a
i
j
=
k
∗
a
i
−
i
k
∈
Z
+
\begin{aligned} &a_j=\frac{i+j}{a_i}\\ &j=k*a_i-i\quad k \in Z^+\\ \end{aligned}
aj=aii+jj=k∗ai−ik∈Z+
详细的找的话k第一个取值大概看下就是:
i
<
j
k
∗
a
i
−
i
=
j
>
i
k
∗
a
i
>
2
∗
i
k
>
2
∗
i
a
i
k
∈
Z
+
k
=
⌈
2
∗
i
a
i
⌉
j
=
⌈
2
∗
i
a
i
⌉
∗
a
i
−
i
\begin{aligned} &i<j\\ &k*a_i-i=j>i\\ &k*a_i>2*i\\ &k>\frac{2*i}{a_i}\quad k \in Z^+\\ &k=\lceil \frac{2*i}{a_i}\rceil\\ j=\lceil \frac{2*i}{a_i}\rceil *a_i-i \end{aligned}
j=⌈ai2∗i⌉∗ai−ii<jk∗ai−i=j>ik∗ai>2∗ik>ai2∗ik∈Z+k=⌈ai2∗i⌉
之后每次自增a[i]
查找直到满足条件
不嫌丢人,我vector写挂了???(反思*2
/*
* @Descripttion:
* @Author: ssw
* @Date: 2021-05-30 04:49:52
* @LastEditors: ssw
* @LastEditTime: 2021-06-26 00:49:37
*/
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
using ll = long long;
int n, m;
int main(){
cin >> n;
while(n--)
{
cin >> m;
ll data[100005];
ll sum=0;
for (int i = 1; i <= m;++i)
{
cin >> data[i];
}
for (int i = 1; i < m;i++)
{
ll k = ceil(2.0 * i / data[i]);
// cout << i << ' '<<k<<endl;
for (ll j = k * data[i] - i; j <= m; j += data[i])
{
if(j+i==data[i]*data[j]&&j>i)
sum++;
}
}
cout << sum << endl;
}
return 0;
}
C. Great Graphs
题目挺巧妙,闲了继续写
6.26更新:
总结:给出dist
数组,有负边但是不存在那种越搞越小的,暗示临近点之间负边有对应正边
想法:刚做的时候就把dist数组当成前缀和数组去做了后来发现问题很大,理解起来就是图中的边要自己构造给出了距离数组,可以先默认是个点集合然后把点的顺序做个变化,排序之后就变成一个递增数组,图像就变成了下面这样:
其中a,b,c
均大于零,因为先将dist数组排序了
其实还能这样在进一步理解我说的临近边有负边:
之后计算的时候就要忽略临近边的计算了,因为条件临近边的值已经相互抵消了
那么答案就来到了:把这些边加起来边负号就是能拥有的最大负边数
直接算跨过两个边的:1->3,2->4
,跨过三个边的:1->4
计算还是要加起来
可见是可以相互化简得,所以这个问题复杂度就是排序复杂度
还有一点就是注意longlong和输入数据量大小
不然就不会像我一样wa完又T了
/*
* @Descripttion:
* @Author: ssw
* @Date: 2021-05-30 04:49:52
* @LastEditors: ssw
* @LastEditTime: 2021-06-26 14:32:44
*/
#include<iostream>
#include<vector>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
using ll = long long;
int n, m;
bool cmp(ll a, ll b){
return a < b;
}
int main(){
cin >> n;
while(n--)
{
cin >> m;
ll data[100005];
ll sum=0;
for (int i = 1; i <= m;++i)
{
scanf("%lld", &data[i]);
}
sort(data + 1, data + m + 1, cmp);
// for (int i = 1; i <= m; ++i)
// {
// cout << data[i] << endl;
// }
if(m<=2)
{
cout << 0 << endl;
continue;
}
for (int i = 2; i < m;++i)
{
if(m*1.0/i>2)
{
for (int j = 1; j <= i; ++j)
{
sum += (data[m - j + 1] - data[j]);
}
}
else
{
for (int j = 1; j <= m - i; ++j)
{
sum += (data[m - j + 1] - data[j]);
}
}
// for (int j = 1; j <= m - i; ++j)
// {
// ll num = (data[j + i] - data[j]);
// if(num>0)
// sum -= num;
// else
// sum += num;
// // cout << sum << endl;
// }
}
// cout << -sum << endl;
printf("%lld\n", -sum);
// if (sum > 0)
// cout << -sum * 2 << endl;
// else
// cout << sum * 2 << endl;
}
return 0;
}