2021东北四省赛补题/个人题解

Dashboard - The 15th Chinese Northeast Collegiate Programming Contest - Codeforces

I

模拟

#include <bits/stdc++.h>
using i64 = long long;
using namespace std;
#define int long long
int mp[8] = {0, 7, 27, 41, 49, 63, 78, 108};
void solve()
{
	int n; cin >> n;
	vector<int>a(n + 1);
	int s = 0;
	for(int i = 1; i <= n; i ++) 
	{
		cin >> a[i];
		s += mp[a[i]];
	}
	if(s >= 120) s -= 50;
	else if(s >= 89) s -= 30;
	else if(s >= 69) s -= 15;
	cout << s << '\n';
}
signed main() 
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int t = 1; std::cin >> t;
    while (t--) 
	{
        solve();
    }
}

E. Easy Math Problem

赛时太Push也不好,还是得好好看题目

样例即答案

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define int long long
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
void solve()
{
	int x; cin >> x;
	cout << 24 * x  << " " << 4 << '\n';
	cout << 2 * x << " " << 4 * x << " " << 6 * x << " " << 12 * x << '\n';
}
signed main() 
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int t = 1; cin >> t;
	while(t --) solve();
}

M

看了好久没太懂题目意思,这是考的观察表格能力?。。。

①长度1、2特判

②韵母只有ang特判,其他的韵母能单独成字的都长度都小于3归为上一类(观察得到的。。。

③声母长度最多为2,剩下都为韵母

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1005;
map<string, string> mp = 
{
	{"q","q"}, {"iu","q"},{"w","w"}, {"ei","w"}, {"r","r"}, {"uan","r"},{"t","t"}, {"ue","t"},
	{"y","y"}, {"un","y"},{"u","u"}, {"sh","u"}, {"i","i"}, {"ch","i"},{"o","o"}, {"uo","o"},
	{"p","p"}, {"ie","p"},{"a","a"}, {"s","s"}, {"ong","s"}, {"iong","s"},{"d","d"}, {"ai","d"},
	{"f","f"}, {"en","f"},{"g","g"}, {"eng","g"}, {"h","h"}, {"ang","h"},{"j","j"}, {"an","j"},
	{"k","k"}, {"uai","k"},{"ing","k"}, {"l","l"}, {"uang","l"}, {"iang","l"},{"z","z"}, {"ou","z"},
	{"x","x"}, {"ia","x"},{"ua","x"}, {"c","c"}, {"ao","c"}, {"v","v"},{"zh","v"}, {"ui","v"},
	{"b","b"}, {"in","b"},{"n","n"}, {"iao","n"}, {"m","m"}, {"ian","m"}, {"e","e"}
};


signed main() 
{
	ios::sync_with_stdio(0);
//	cin.tie(0); cout.tie(0);
	string line;
	while(getline(cin, line))
	{
		stringstream ss(line);
		string s;
		while(ss >> s)
		{
			if(s.size() == 2) cout << s << ' ';
			else if(s.size() == 1) cout << s << s << ' ';
			else
			{
				if(s.substr(0, 3) == "ang") cout << "a" << mp["ang"] << ' ';
				else
				{
					if(mp.count(s.substr(0, 3)))
					{
						cout << mp[s.substr(0, 3)];
						s = s.substr(3);
					}
					else if(mp.count(s.substr(0, 2)))
					{
						cout << mp[s.substr(0, 2)];
						s = s.substr(2);
					}
					else if(mp.count(string(1, s[0])))
					{
						cout << mp[string(1, s[0])];
						s = s.substr(1);				
					}
					cout << mp[s] << ' '; 					
				}

			}
			
		}
		cout << '\n'; 
	}
}

K

设伤害为 x ,小于 x 的边都是不存在的,大于等于的都是存在的。

先并查集+后缀和求剩m~1条边的联通情况

查询时二分找到该伤害能摧毁多少条边

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
//#define int long long
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int p[N];
int find(int x)
{
	if(x != p[x]) p[x] = find(p[x]);
	return p[x];
}
void solve()
{
	int n, m, Q; cin >> n >> m >> Q;
	vector<ll>val(m + 1), cnt(n + 1);
	for(int i = 1; i <= n; i ++) p[i] = i, cnt[i] = 1;
	vector<pair<int, pair<int, int>>>a;
	for(int i = 1; i <= m; i ++)
	{
		int x, y, k; cin >> x >> y >> k;
		a.push_back(make_pair(k, make_pair(x, y)));
	}
	sort(a.begin(), a.end());
	val[m] = 0;
	for(int i = m - 1; i >= 0; i --)
	{
		int x = a[i].second.first, y = a[i].second.second;
		x = find(x), y = find(y);
		val[i] = val[i + 1];
		if(x != y)
		{
			val[i] = val[i + 1] + (ll)cnt[x] * cnt[y];
			cnt[x] += cnt[y], p[y] = x;			
		}
//		cout << i << " " << val[i] << '\n';
	}
	while(Q --)
	{
		int x; cin >> x;
		x = lower_bound(a.begin(), a.end(), make_pair(x, make_pair(0, 0))) - a.begin();
		cout << val[x] << '\n';
	}
}
signed main() 
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int t = 1; cin >> t;
	while(t --) solve();
}

A

对于1~n的每个数i单独求贡献

放i选某行:n

选与i同行的元素:C(n * n, n * n - i) 从比i大的选

排该行的顺序:n!

排剩下的元素的顺序:(n * n - n)!   这一步不要漏了,放置完所有元素才算一种矩阵排法

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
const int mod = 998244353;
const int N = 3e7 + 10;
int fac[N], infac[N];
/*
7
1
2
3
4
5
1000
5000


*/
int qmi(int a, int b, int q)
{
	a %= mod;
    int res = 1ll;
    while(b)
    {
        if(b & 1) res = (ll)res * a % mod;
        a = (ll)a * a % mod;
        b >>= 1ll;
    }
    return res % mod;
}
int A(int a, int b)
{
	a = (a + mod) % mod, b = (b + mod) % mod;
	if(a == 0 || b == 0) return 1;
    int res = (ll)fac[a] * infac[a - b] % mod;	
    
	return res;
}
int C(int a, int b)
{
	a = (a + mod) % mod, b = (b + mod) % mod;
	if(a == 0 || b == 0) return 1;
    int res = (ll)fac[a] * infac[b] % mod * infac[a - b] % mod;    
	return res;	
}
void solve()
{
	int n; cin >> n;
	int ans = 0;
	for(int i = 1; i <= n; i ++)
	{
		ans += n * fac[n * n - n] % mod * C(n * n - i, n - 1) % mod * fac[n];
		ans %= mod;
	}
	cout << ans % mod << '\n';
}
signed main() 
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    fac[0] = 1;
    for(int i = 1; i <= N; i ++)
    {
        fac[i] = (ll)fac[i - 1] * i % mod;
    }
    infac[N] = qmi(fac[N], mod - 2, mod);
    for(int i = N - 1; i >= 0; i --)
    {
        infac[i] = (ll)infac[i + 1] * (i + 1) % mod;
    }
	int t = 1; std::cin >> t;
    while (t --) 
	{
        solve();
    }
}

C

属于有点难想状态设计,但是看题解一眼懂类型

贴个大佬代码【解题报告】2021CCPC东北四省赛_2021东北四省赛-CSDN博客

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,mod=998244353;
typedef long long LL;
int n;
vector<int>v[N];
LL f[N][3];

void dfs(int u,int fa){
	f[u][0]=f[u][1]=f[u][2]=1;
    for(int j:v[u]){
    	if(j==fa)continue;
        dfs(j,u);
        //递归完后开始更新子树,然后一层层向上更新
        f[u][0]=f[u][0]*(f[j][0]+f[j][1])%mod;
        f[u][1]=f[u][1]*(f[j][0]+f[j][1]+f[j][2])%mod;
        f[u][2]=f[u][2]*f[j][0]%mod;
    }
    f[u][1]-=f[u][2];
    if(f[u][1]<0)f[u][1]+=mod;
}
int main(){
	int T;
	while(~scanf("%d",&T)){
		while(T--){
			scanf("%d",&n);
			for(int i=1;i<=n;i++)v[i].clear();
			
		    for(int i=0,a,b;i<n-1;i++){
		        scanf("%d%d",&a,&b);
		        v[a].push_back(b);
		        v[b].push_back(a);
		    }
		   	dfs(1,-1);
		    printf("%lld\n",(f[1][0]+f[1][1])%mod);
		}
	}
    return 0;
}

后面的题随缘补

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值