北大没做北化校赛血亏
离世界第一就差一个北化
目录
问题 A: 坤坤大闹天宫1
难度指数:⭐⭐
小思维
因为
落在
我们设
当
大于120时,
就大于
了,所以答案一定在
直接跑一遍二重循环即可
代码如下
typedef long long ll;
int main()
{
ll x;
cin>>x;
for(ll i=-120;i<=120;i++){
for(ll j=-120;j<120;j++)
if(i*i*i*i*i-j*j*j*j*j==x){
cout<<i<<" "<<j;
return 0;
}
}
return 0;
}
问题 B: 坤坤大闹天宫2
难度指数:⭐
直接按题目意思模拟即可
代码如下
int a[N];
int main()
{
int n,k,t;
cin>>n>>k;
while(k--){
cin>>t;
while(t--){
int kk;
cin>>kk;
a[kk]++;
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(a[i]==0) ans++;
}
cout<<ans<<endl;
return 0;
}
问题 C: 坤坤大闹天宫3
难度指数:⭐⭐
因为
很小,只有12
所以这是一道经典的搜索问题
爆搜即可
代码如下
const int N=15;
typedef long long ll;
int n,m,x;
int cost[N];
int w[N][N];
int v[N];
int mincost=0x3f3f3f3f;
int sumcost=0;
void dfs(int u)
{
if(u==n) return;
sumcost+=cost[u];//选择这本书u
for(int i=0;i<m;i++) v[i]+=w[u][i];
bool flag=1;
for(int i=0;i<m;i++) if(v[i]<x) flag=0;
if(flag)
if(sumcost<mincost) mincost=sumcost;
dfs(u+1);//进入下一本书的选择
sumcost-=cost[u];
for(int i=0;i<m;i++) v[i]-=w[u][i];
dfs(u+1);//不选这本书u,进入下一本书的选择
}
int main()
{
cin>>n>>m>>x;
for(int i=0;i<n;i++)
{
cin>>cost[i];
for(int j=0;j<m;j++) cin>>w[i][j];
}
dfs(0);
if(mincost==0x3f3f3f3f) cout<<"-1";
else cout<<mincost;
return 0;
}
问题 D: 坤坤大闹天宫4
难度指数:⭐⭐⭐⭐
这道题想法可以有很多
这里说其中一种
隔板法:n个球,就有n+1个隔板,除了最两边的隔板外,每删除一个隔板,相当于把相邻的球弄为一种颜色,最多有k个相邻,说明最多可以删除k个隔板,然后同一个隔板内部的可以视为一个整体,相当于一种颜色,第一个隔板内部有m个选择,第二个有m-1个选择,第三个也有m-1个选择,直到最后一个,所以公式就是
代码如下:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5 + 10;
const ll mod = 998244353;
ll fact[N], infact[N];
ll n, m, k;
ll qmi(ll a, ll k, ll p) {
int res = 1;
while (k) {
if (k & 1) res = (ll)res * a % p;
a = (ll)a * a % p;
k >>= 1;
}
return res;
}
void init() {
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i++) {
fact[i] = (ll)fact[i - 1] * i % mod;
infact[i] = (ll)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
}
}
int main() {
init();
cin >> n >> m >> k;
ll res = 0;
for (int i = 0; i <= k; i++) {
int a = n - 1, b = i;
res = (ll)res + m * fact[a] % mod * infact[b] % mod * infact[a - b] %mod * qmi(m - 1, n - 1 - i, mod) % mod;
res = res % mod;
}
cout << res << endl;
}
问题 E: 坤坤大闹天宫5
难度指数:⭐⭐⭐
贪心,判断括号匹配的字符串问题
首先给出的所有字符串的左右括号数是要匹配的
接下来判断这些字符串能否构成合理的括号序列,可以用pair存储每个字符串需要的匹配数和需要的右括号数
我们试想,合法的括号序列一定是左括号尽量靠左,右括号靠右的,所以我们要对其就行排序,最后用一个变量记录当前的待匹配数res,如果pair 的右括号数超过待匹配数,则输出No
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
const int M = 1e5+7;
char s[M];
struct na{
int x,y;
bool operator <(const na &r)const
{
return y<r.y;
}
};
struct nb{
int x,y;
bool operator <(const nb &r)const
{
return x>r.x;
}
};
vector<na>va;
vector<nb>vb;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s;
int l=strlen(s);
int a=0,b=0;
for(int j=0;j<l;j++)
{
if(s[j]=='(')a++;
else
{
if(a)a--;
else b++;
}
}
//这里a的意思是需要在这个字符串后面补多少右括号,b是需要在其前面补多少左括号
//当a>b时,说明做左括号比右括号多,肯定优先放前面。显然,此时b越小在前面越优,因为需要在前面补左括号的个数就少了
//a<b时同理
// cout<<a<<" "<<b<<endl;
if(a>=b)va.pb(na{a,b});
else vb.pb(nb{a,b});
}
sort(va.begin(),va.end());
sort(vb.begin(),vb.end());
bool f=true;
int sm=0;
for(int i=0;i<va.size();i++)
{
sm-=va[i].y;
if(sm<0)f=false;//前面的左括号能否满足当前字符串的需要
sm+=va[i].x;//当前字符串所能提供的左括号
//肯定是左括号需求量少的在前面
}
for(int i=0;i<vb.size();i++)
{
sm-=vb[i].y;
if(sm<0)f=false;
sm+=vb[i].x;
//右边肯定是对称的来考虑,即需求后面右括号少的放在最右边
}
if(sm!=0)f=false;
if(f)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}
问题 F: 坤坤大闹天宫6
难度指数:⭐⭐⭐⭐
首先给出结论:后手必胜当且仅当这棵树有完美匹配
(完美匹配:我们定义一组节点是两个节点且这两个节点间连一条边,如果一棵树可以分成若干个这样的组,那么说这棵树拥有完美匹配)
这棵树有完美匹配的时候,因为先手染什么颜色后手只要染它的匹配,就能保证每个白色节点有至少一个与它相邻的黑色节点了
如果一个点连着两个以上的叶子必定是先手必胜了,所以接下来我们默认所有的点连着的叶子个数小于等于1
如果没有完美匹配,我们随便找一个点为根,然后对于一个叶子,先手把它的父亲染白,那么后手必须把这个叶子染黑。然后我们把这两个点从树中删去,继续操作。显然树不会被删完,否则就存在完美匹配了。此时我们随便染白一个还未染的点就赢了
于是充要性都有了
求完美匹配直接从叶子开始贪心
代码如下
#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair<int,int>
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
template <typename _Tp>void input(_Tp &x){
char ch(getchar());bool f(false);while(!isdigit(ch))f|=ch==45,ch=getchar();
x=ch&15,ch=getchar();while(isdigit(ch))x=x*10+(ch&15),ch=getchar();
if(f)x=-x;
}
template <typename _Tp,typename... Args>void input(_Tp &t,Args &...args){input(t);input(args...);}
const int N=1e6+10;
vector<int> v[N];
int vis[N];
void dfs(int son,int fa){
for(auto t:v[son]){
if(t==fa) continue;
dfs(t,son);
}
if(!vis[son]&&vis[fa]){
puts("First");
exit(0);
}
if(!vis[son]){
vis[son]=vis[fa]=1;
}
}
signed main()
{
int n;
cin>>n;
fer(i,1,n-1){
int a,b;
cin>>a>>b;
v[a].pb(b);
v[b].pb(a);
}
vis[0]=1;
dfs(1,0);
puts("Second");
}