C.Many Medians
(水题)
题意:给出一个n(n必为偶数),随后是n个数b[i],问你从中取走第i个数后的第(n+1)/ 2 大的数是多少,要求求出取走所有b[i]的情况(取后会放回)
题解:开一个a[]数组,令每个a[i]=b[i],然后对a[]数组排序,得到中间值a[mid],(mid=n/2)之后每次比较被取走的b[i]和a[mid]的大小关系,如果b[i]<=a[mid]就取a[mid+1],反之取a[mid]即可。
Eg:1 2 3 4 5 6 ,中间值a[mid]=3,若取走的是1或2或3,就输出4,取走的是4或5或6就输出3。you know!
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 2e5 + 500;
int a[maxn],b[maxn];
int main(){
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(a + 1, a + n + 1);
int mid = n / 2;
for (int i = 1; i <= n; i++)
{
if (b[i] <=a[mid])
cout << a[mid+1] << endl;
else if(b[i]>a[mid])
cout << a[mid]<< endl;
}
return 0;
}
D.Binomial Coefficients
(结论提)
题意:给出n个数a[i],求的最大值并输出其ai,aj.
题解:当n接近时有
,且此时也是
的最大值,而且此时我们只需要对a[]数组进行排序然后二分查找到第一个大于
的数a[x],则可以得到最大值为
.(不过有一点要注意的是当m为奇数时中间值存在2个Eg:
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 2e5 + 500;
int a[maxn];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
sort(a, a + n);
int MAX = a[n - 1], x = a[n - 1] / 2;
int p = lower_bound(a, a + n - 1, x) - a;
cout << a[n - 1] << " ";
if (a[p] == x)
cout << x << endl;
else if (MAX % 2 == 1)
{
if (a[p] == x || a[p] == x + 1)
cout << a[p] << endl;
else
{
int xx = min(abs(a[p] - x), abs(a[p] - x - 1));
int yy = min(abs(a[p - 1] - x), abs(a[p - 1] - x - 1));
if (xx < yy)
cout << a[p] << endl;
else
cout << a[p - 1] << endl;
}
}
else
{
int xx = abs(a[p] - x);
int yy = abs(a[p - 1] - x);
if (xx < yy)
cout << a[p] << endl;
else
cout << a[p - 1] << endl;
}
return 0;
}
E.Symmetric Grid
( 思维+dfs)
题意:给出一个n*m的字符串矩阵,问你它能否经过行和列的任意调换得到一个中心对称矩阵.
题解:先dfs对行进行随机配对,并记录当前配对结果marry[i]=j,当两两配对完成后,在判断列列能否在当前行的配对下两两配对(这里的两两配对是需要满足中心对称的,前一个行的不需要考虑),若是可以输出YES,不行回溯到dfs处,轮到其他marry配对情况,当他们也行的两两配对完再次进行check(),直到所有行的;两两配对都无法得到一组能结果列变换得到中心对称的矩阵输出NO.(有一点要注意的是奇数的情况会多出来一行特殊处理)
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 2e5 + 500;
bool vis[15], flag;
char str[15][15];
int marry[15];
int n, m;
bool check_c(int x, int y) {//判断这两列是否满足中心对称
for (int i = 0; i < n; i++)
if (str[marry[i]][x] != str[i][y])return false;
return true;
}
bool check() {//在行随机匹配完成后进行判断是否满足通过列的配对得到中心对称的图像
memset(vis, 0, sizeof(vis));
for (int i = 0; i < m; i++)
{
if (vis[i])continue;
for (int j = i + 1; j < m; j++)
if (!vis[j] && check_c(i, j))
{
vis[i] = true;
vis[j] = true;
break;
}
}
int x = -1;
for (int i = 0; i < m; i++)
if (!vis[i]) {
if (m % 2 == 1 && x == -1 && check_c(i, i)) //判断m为奇数时多余出来的一行能否自身对称
x = i;
else
return false;
}
return true;
}
void dfs(int u) {//每次dfs随机匹配2行
if (u == n / 2) {//直到u为n的一半时偶数匹配完了,奇数剩一行
int x;
if (n % 2 == 1) {//若是n为奇数则需要有一行自身匹配
for (int i = 0; i < n; i++)
if (marry[i] == -1)
marry[i] = x = i;
}
if (check())
flag = true;
if (n % 2 == 1)marry[x] = -1;//注意n为奇数的情况check()完要初始化
return;
}
for (int i = u; i < n; i++) {//注意这里i从u开始,对前面已经使用过的i进行剪枝
if (marry[i] != -1)continue;
for (int j = i + 1; j < n; j++) {//这里j从i+1开始也是剪枝,否则都从0开始时间复杂度为O(n!)
if (marry[j] == -1)
{
marry[i] = j;
marry[j] = i;
dfs(u + 1);
if (flag)return;
marry[i] = -1;//记得把之前的数据初始化
marry[j] = -1;//以便之后继续进行其他行的随机配对
}
}
}
}
int main() {
while (~scanf("%d%d", &n, &m)) {
for (int i = 0; i < n; i++) {
scanf("%s", &str[i]);
marry[i] = -1;
}
flag = false;
dfs(0);
if (flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
F题木有做阿~