首页 > 其他分享 >2019 CSP-J 江西

2019 CSP-J 江西

时间:2024-01-15 23:01:11浏览次数:28  
标签:江西 le int lnt 2019 ans rightarrow CSP dis

2019 CSP-J 江西

P5681 面积(语法)

题意

求出边长为 \(a\) 的正方形与长宽分别为 \(b,c\) 的矩形哪一个面积更大。

题解

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
void Solve(void)
{
	lnt a, b, c;
	cin >> a >> b >> c;
	if (a * a > b * c)
	{
		cout << "Alice" << endl;
	}
	else
	{
		cout << "Bob" << endl;
	}
}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

P5682 次大值(数学,STL)

题意

\(n\) 个正整数,求出所有的 \(a_i \bmod a_j (1 \le i,j \le n \wedge i \neq j)\) 中严格次大值是多少。

数据规模与约定

对于 \(100\%\) 的数据,\(3 \le n \le 2\times 10^5\),\(1\le a_i \le 10^9\)。

题解

对于 \(70\%\) 的数据显然我们可以暴力。

考虑对于 \(100\%\) 的数据怎么办。首先我们假设 \(a \bmod b = c\):

  1. 当 \(a < b\) 时,\(c=a<b\)。

  2. 当 \(a=b\) 时,\(c=0\)。

  3. 当 \(a>b\) 时,\(c<b<a\)。

综上,\(c \le min(a,b),c \ne max(a,b)\)。所以序列中的最大值一定无法取到。

现在我们不妨假设 \(a\) 为最大值,\(b\) 为次大值。我们有以下结论:\(a \bmod b<b,b \bmod a=b\)。

所以当使用次大值 \(b\) 对最大值 \(a\) 取模时,我们能获得 \(c\) 的最大值。证明可以使用反证法:若存在比 \(c=b\) 更大的值 \(b'\),即存在 \(b'\),使得 \(b' \bmod a=b'>b\)。与 \(b\) 为次大值矛盾。

那么同理若 \(b\) 为次次大值时,获得的 \(c\) 为次大值。

所以我们发现,只有最大的三个不同的数是有效的。

因为要分类讨论有效的数为 \(1,2,3\) 时的情况,所以我们不如直接对有效的数进行 \(70\%\) 部分的暴力做法。

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
int n;
set<int>lib;
/*====================*/
void Solve(void)
{
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		int temp; cin >> temp; lib.insert(temp);
	}
	vector<int>usefulnum;
	for (auto it = lib.rbegin(); it != lib.rend() && usefulnum.size() < 3; ++it)
	{
		usefulnum.push_back(*it);
	}
	vector<int>ans;
	for (int i = 0; i < usefulnum.size(); ++i)
	{
		for (int j = 0; j < usefulnum.size(); ++j)
		{
			if (i != j)
			{
				ans.push_back(usefulnum[i] % usefulnum[j]);
			}
		}
	}
	sort(ans.begin(), ans.end());
	ans.erase(unique(ans.begin(), ans.end()), ans.end());
	reverse(ans.begin(), ans.end());
	if (ans.size() <= 2)
	{
		cout << "-1" << endl;
	}
	else
	{
		cout << ans[1] << endl;
	}
}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

P5683 道路拆除(最短路)

题意

给定一张 \(n\) 点 \(m\) 边的无向图,边权为 \(1\)。求最多可以删多少条边,使得从 \(1\) 号点出发,能到达 \(s_1\) 号点与 \(s_2\) 号点,且经过的边的数量分别不超过 \(t_1\) 与 \(t_2\)。若无论如何都不能,则输出 \(-1\)。

数据规模与约定

对于 \(100\%\) 的数据,\(2 \le n,m \le 3000\),\(1\le x,y \le n\),\(2 \le s_1,s_2 \le n\),\(0 \le t_1,t_2 \le n\)。

题解

我们发现题目的要求只和三个点有关:\(1,s_1,s_2\)。

考虑从 \(1\) 号点分别到 \(s1,s2\) 的路径形态:

  1. \(1 \rightarrow ...\rightarrow s_1\rightarrow ...\rightarrow s_2\)。
  2. \(1 \rightarrow ...\rightarrow s_2\rightarrow ...\rightarrow s_1\)。
  3. \(1\rightarrow \begin{cases} ...\rightarrow s_1\\...\rightarrow s_2 \end{cases}\)
  4. \(1\rightarrow ... \rightarrow x \rightarrow \begin{cases} ...\rightarrow s_1\\...\rightarrow s_2 \end{cases}\)

我们发现,所有形态都可以归结到第四种形态,只不过第一种形态 \(x=s_1\),第二种形态 \(x=s_2\),第三种形态 \(x=1\)。

于是我们分别求出 \(1,s_1,s_2\) 到所有点的最短路径,然后枚举 \(x\) 即可。

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
const int N = 3e3 + 10;
const int M = 3e3 + 10;
/*====================*/
const int INF = 0X3F3F3F3F;
/*====================*/
int n, m;
int s1, t1;
int s2, t2;
/*====================*/
namespace _Graph
{
	struct Edge
	{
		int u, v;
		Edge(int _u = 0, int _v = 0)
		{
			u = _u, v = _v;
		}
		int node(int x)const
		{
			return x == u ? v : u;
		}
	};
	/*====================*/
	int cntedge;
	Edge edge[M];
	vector<int>G[N];
	/*====================*/
	void AddEdge(int u, int v)
	{
		edge[++cntedge] = Edge(u, v);
		G[u].push_back(cntedge);
		G[v].push_back(cntedge);
	}
}
/*====================*/
int dis_s0[N], dis_s1[N], dis_s2[N];
/*====================*/
namespace _Dijkstra
{
	using namespace _Graph;
	/*====================*/
	struct Unit
	{
		int v, w;
		Unit(int _v = 0, int _w = 0)
		{
			v = _v, w = _w;
		}
		friend bool operator<(const Unit& a, const Unit& b)
		{
			return a.w > b.w;
		}
	};
	/*====================*/
	bool vis[N];
	/*====================*/
	void Init(int s, int dis[])
	{
		memset(vis, false, sizeof(vis));
		priority_queue<Unit>q;
		q.push(Unit(s, dis[s] = 0));
		while (!q.empty())
		{
			int cur = q.top().v; q.pop();
			if (vis[cur])continue; vis[cur] = true;
			for (int i = 0; i < G[cur].size(); ++i)
			{
				int nxt = edge[G[cur][i]].node(cur);
				if (dis[nxt] > dis[cur] + 1)
				{
					dis[nxt] = dis[cur] + 1;
					q.push(Unit(nxt, dis[nxt]));
				}
			}
		}
	}
}
/*====================*/
void Solve(void)
{
	cin >> n >> m;
	for (int i = 1; i <= m; ++i)
	{
		int u, v; cin >> u >> v;
		_Graph::AddEdge(u, v);
	}
	cin >> s1 >> t1 >> s2 >> t2;

	memset(dis_s0, INF, sizeof(dis_s0)); _Dijkstra::Init(01, dis_s0);
	memset(dis_s1, INF, sizeof(dis_s1)); _Dijkstra::Init(s1, dis_s1);
	memset(dis_s2, INF, sizeof(dis_s2)); _Dijkstra::Init(s2, dis_s2);

	int ans = -1;
	for (int i = 1; i <= n; ++i)
	{
		if (dis_s1[i] + dis_s0[i] <= t1 && dis_s2[i] + dis_s0[i] <= t2)
		{
			ans = max(ans, m - (dis_s0[i] + dis_s1[i] + dis_s2[i]));
		}
	}
	cout << ans << endl;
}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

P5684 非回文串(组合计数)

题意

给定 \(n\) 个小写英文字符,从 \(1 \sim n\) 编号,分别为 \(c_1,c_2, \dots , c_n\)。

将这些字符重新排列,组成一个字符串 \(S\)。求一共有多少种不同的排列字符的方案,能使得 \(S\) 是个非回文串。

数据规模与约定

对于 \(100\%\) 的数据,\(3 \le n \le 2000\)。

题解

正难则反,用总排列方案数减去回文串排列方案数即为非回文串排列方案数

如何求总排列方案数?\(n\) 个字符,一共有 \(A^n_n=n!\) 种排列方案。

如何求回文串排列方案数?分两步:

  1. 求出本质不同的回文串的个数。
  2. 对于每一个本质不同的回文串,乘上每一种字符的排列方案数。

值得注意的是,出现次数为奇数次的字符,最多有一种。否则不能组成回文串。

第一步对应下面代码的69-74行,第二步对应下面代码的75-79行。

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
const int N = 2e3 + 10;
/*====================*/
const lnt MOD = 1e9 + 7;
/*====================*/
int n;
string str;
int cnt[26];
/*====================*/
lnt factorial[N];
/*====================*/
class INV
{
public:
	lnt operator[](lnt x)
	{
		return Pow(x % MOD, MOD - 2);
	}
private:
	lnt Pow(lnt a, lnt b)
	{
		lnt res = 1;
		while (b)
		{
			if (b & 1)
			{
				res = (res * a) % MOD;
			}
			b >>= 1, a = (a * a) % MOD;
		}
		return res;
	}
}inv;
/*====================*/
void Solve(void)
{
	cin >> n >> str;
	/*====================*/
	for (auto c : str)
	{
		cnt[c - 'a']++;
	}
	/*====================*/
	factorial[0] = 1;
	for (int i = 1; i <= n; ++i)
	{
		factorial[i] = (factorial[i - 1] * lnt(i)) % MOD;
	}
	lnt tot = factorial[n];
	/*====================*/
	int odd = 0;
	for (int i = 0; i < 26; ++i)
	{
		if (cnt[i] & 1)
		{
			odd++;
		}
	}
	/*====================*/
	lnt palindrome = 0;
	if (odd <= 1)
	{
        //计算本质不同的回文串方案数
		palindrome = factorial[n / 2];
		for (int i = 0; i < 26; ++i)
		{
			palindrome = (palindrome * inv[factorial[cnt[i] / 2]]) % MOD;
		}
        //乘以每种字符排列的方案数
		for (int i = 0; i < 26; ++i)
		{
			palindrome = (palindrome * factorial[cnt[i]]) % MOD;
		}
	}
	/*====================*/
	cout << (tot - palindrome + MOD) % MOD << endl;
}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

标签:江西,le,int,lnt,2019,ans,rightarrow,CSP,dis
From: https://www.cnblogs.com/ProtectEMmm/p/17966603

相关文章

  • 2020 CSP-J
    P7071优秀的拆分(语法)题意给定一个正整数,输出二进制拆分。如果这个数是奇数输出-1。数据规模与约定对于\(100\%\)的数据,\(1\len\le10^7\)。题解#include<bits/stdc++.h>usingnamespacestd;/*====================*/#defineendl"\n"/*====================*/......
  • 2021 CSP-J
    P7909分糖果(数学)题意给定\(n,l,r\),求一个数\(x\),当\(l\lex\ler\)时,最大的\(x\bmodn\)。数据规模与约定对于\(100\%\)的数据,\(1\len\lel\ler\le10^9\)。题解假设\(l=K_l*n+R_l,r=K_r*n+R_r,x=K_x*n+R_x\)。我们要求\(R_x\)尽......
  • 2019 CSP-J
    P5660数字游戏(语法)题意给定一个长度最大为\(8\)的01字符串,求字符串中有多少个\(1\)。题解#include<bits/stdc++.h>usingnamespacestd;/*====================*/#defineendl"\n"/*====================*/typedeflonglonglnt;/*====================*/voidSo......
  • 2023 CSP-J
    P9748小苹果(模拟)题意\(n\)个苹果从左到右排成一列,编号为从\(1\)到\(n\)。每天从左侧第\(1\)个苹果开始,每隔\(2\)个苹果拿走\(1\)个苹果。求出多少天能拿完所有的苹果,编号为\(n\)的苹果是在第几天被拿走。数据规模与约定对于\(100\%\)的数据,\(1\len\le10^9......
  • 2022 CSP-J
    P8813乘方(数学,模拟)题意给定两个数\(a,b\),如果\(a^b\le10^9\),输出\(a^b\)的值。否则输出\(-1\)。数据规模与约定对于\(100\%\)的数据,\(1\lea,b\le10^9\)。题解记得开longlong。如果\(a=1\),那么无论\(b\)是多少结果都是\(1\)。如果\(a\ne1\),那么\(a......
  • [极客大挑战 2019]HTTP 1
    [极客大挑战2019]HTTP1审题看到题目页面发现没啥东西,直接看源码发现了,Secret.php进入查看题目,发现又是一道跟着提示达到条件的题目知识点跟着题目走。解题题目说不是来自https://Sycsecret.buuoj.cn的访问,但是我们发现没有Referer,所以我们加入表示来源看到回显,他......
  • WindowsServer 2019安装域服务
    WindowsServer2019安装域服务导航目录WindowsServer2019安装域服务导航一、重命名主控服务器固定IP地址重命名域控服务器二、登录并创建服务三、检验安装域服务一、重命名主控服务器固定IP地址右击电脑右下角网络的标志,点击打开“网络和internet”设置,在屏幕中间的......
  • [极客大挑战 2019]LoveSQL 1
    [极客大挑战2019]LoveSQL1审题又是一道SQL题,还和上面Easy_SQL是一个系列的题。知识点SQL注入之联合查询。知识点详解联合查询基础讲解:union联合查询定义是:可以使用UNION操作符,将多个查询结果,按行进行纵向合并。基本语法SELECT<字段名>FROM<表名>UNIONSELECT<字......
  • P5501 [LnOI2019] 来者不拒,去者不追 题解
    题目链接:来者不拒,去者不追直接在线查询题目所给的式子是很困难的,我们考虑单点考察贡献。对于一个已经确定的式子,我们发现加入一个数或者删除一个数的贡献如图所示:如图所示,在原有的序列为\((1,2,3)\)当中,我们加入新的\(2\)进去,我们观察到每个数的贡献的变化是这样,比\(2\)......
  • P5321 [BJOI2019] 送别 题解--zhengjun
    由于大家的做法需要大量分类讨论和代码量,这里提供一种不怎么分类的,容易实现的做法。首先,由于墙体会随时变化,所以直接对墙体本身维护不是很方便。我们可以牺牲一点常数,对\((i,j)\)建立四个点\(UL_{i,j},UR_{i,j},DL_{i,j},DR_{i,j}\)分别表示\((i-\varepsilon,j-\varepsilo......