A
题意:
给定二维坐标的三个顶点构成一个三角形。请问能否用一条平行于坐标轴的线段将三角形分割成两个非退化的三角形。
核心思路:只有一种情况是无法分割的,那就是是一个直角三角形并且有两条边平行于x轴和y轴,这里有个比较好的点就是我们可以使用set来存放我们的边,看我们的边的减少到个数。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
const int INF = 0x3fff;
int n, a;
int mod = 998244353;
struct {
int x;
int y;
}s[N];
void solve()
{
int x[3];
int y[3];
for (int i = 0;i < 3;i++)
{
cin >> x[i] >> y[i];
}
if (set<int>(x, x + 3).size() == 2 && set<int>(y, y + 3).size() == 2)
{
cout << "NO" << endl;
return;
}
else
{
cout << "YES" << endl;
}
}
int main()
{
int T;
cin >> T;
while (T--)
{
solve();
}
}
B
题意:
给定n个整数,表示塔楼的高度。每次可以将一个更高的塔楼高度减一,更矮的塔楼高度加一,求操作后第一座塔楼高度的最大值。
核心思路:首先我们可以分析下这个东西的性质,其实我们通过模拟两组样例发现就是a[0]和a[i]对半均分.注意这个均分是向上取整,所以这个答案就很明显了,我们只需要一个一个的去遍历碰到比a[0]大的就对半均分.
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
const int INF = 0x3fff;
int mod = 998244353;
int a[N];
struct {
int x;
int y;
}s[N];
void solve()
{
int n;
cin >> n;
for (int i = 0;i < n;i++)
cin >> a[i];
int sum = 0;
int cnt = 0;
sort(a + 1, a + n);
for (int i = 1;i < n;i++)
{
if (a[i] > a[0])
{
a[0] = (a[0] + a[i]+1) / 2;
}
}
cout << a[0] << endl;
}
int main()
{
int T;
cin >> T;
while (T--)
{
solve();
}
}
C
题意:
给定一个数字 n(n≤100) ,问有多少种满足条件的01字符串 s 。
条件由 a[i][j] 给出。
- a[i][j]=1 则 s[i...j] 中只能出现一种字符
- a[i][j]=2 则 s[i...j] 中要出现01两种字符
- a[i][j]=0 则 s[i...j] 中随便
核心思路:首先我们得先观察\(a[i][j]\)的一个性质,先观察\(a[1][i],a[2][i],a[3][i],a[4][i]\cdots a[i][i]\)
,我们知道一定是22221111,这个形式的,这里我们可以选择倒着看,因为他第一个区间的长度是最大的,然后慢慢递减.
-
集合定义:\(f[L][R]\)为\(a[1][R],a[2][R],a[3][R],\cdots,a[i][R]\)构成的序列,并且\([1\cdots L-1]为2,[L,R]为1的方案数\).
-
集合划分:其实这可以看作一个线性dp问题,所以我们可以根据最后一个位置划分。也就是考虑s[R+1]和s[R]是否相等.(1)如果相等那么直接相加就好了(2)如果不相等,那么我们需要重置下前面的内容,移动下L,一定不要忘了我们我们\(f[L][R]\)的定义,我们需要在这个区间里面都是1.
-
可以看图:
-
-
所以状态转移方程也就是:
(f[L][R+1]+=f[L][R])%=mod
(f[R+1][R+1]+=f[L][R])%=mod
#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 10;
typedef long long LL;
const int INF = 0x3fff;
int mod = 998244353;
int n, a[N][N], f[N][N];
struct {
int x;
int y;
}s[N];
//LL qmi(int a, int b)
//{
//
//}
void solve()
{
cin >> n;
for (int i = 1;i <= n;i++)
for (int j = i;j <= n;j++)
cin >> a[i][j];
f[1][1] = 2;
for(int R=1;R<=n;R++)
for (int L = 1;L <= R;L++)
{
int flag = 1;
for (int i = 1;i < L;i++)
{
if (a[i][R] == 1)
flag = 0;
}
for (int i = L;i <= R;i++)
{
if (a[i][R] == 2)
flag = 0;
}
if (!flag)
f[L][R] = 0;
(f[L][R + 1] += f[L][R]) %= mod;
(f[R + 1][R + 1] += f[L][R]) %= mod;
}
int ans = 0;
for (int i = 1;i <= n;i++)
(ans += f[i][n]) %= mod;
cout << ans << endl;
}
int main()
{
int T;
T = 1;
//cin >> T;
while (T--)
{
solve();
}
}
题意:
给定 2n 的参赛选手,其能力值是 [1,2n] 的排列。一共进行 n 轮比赛。每轮比赛和自己相近的选手进行比赛。比如 ,1vs2,3vs4... 然后胜者继续和胜者比。最后在 n 轮游戏后,会有一个选手胜出。给定一个长度为 n 的 01 串, si=0 表示在第i轮能力低的获胜,否则能力高的获胜。求能力值为多少的选手最终可能获胜。
核心思路:如果没有研究出来一般的做法,那就直接找规律。其实位置就会是\(2^{cnt1}\),终止位置是\(2^n-2^{cnt0}+1\).
#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 10;
typedef long long LL;
const int INF = 0x3fff;
int mod = 998244353;
int n, a[N][N], f[N][N];
struct {
int x;
int y;
}s[N];
//LL qmi(int a, int b)
//{
//
//}
void solve()
{
int lt = 0;
int gt = 0;
int n;
cin >> n;
string s;
cin >> s;
for (int i = 0;i < n;i++)
{
if (s[i] == '1')
lt += lt + 1;
else
gt += gt + 1;
}
for (int i = lt+1;i <= (1 << n) - gt;i++)
{
cout << i << " ";
}
cout << endl;
}
int main()
{
int T;
T = 1;
//cin >> T;
while (T--)
{
solve();
}
}
标签:Educational,Rated,const,题意,140,int,cin,solve,mod
From: https://www.cnblogs.com/xyh-hnust666/p/16990907.html