2021SCUACM集训队冬季选拔2大部分题解
Posted hans774882968
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021SCUACM集训队冬季选拔2大部分题解相关的知识,希望对你有一定的参考价值。
本来在预习课程期末的,结果还是没能忍住来写了一套题
A
签到。数有多少个个位为9的。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)
const int N = 3e5 + 5;
int n;
void dbg()puts("");
template<typename T, typename... R>void dbg(const T &f, const R &... r)
cout << f << " ";
dbg(r...);
template<typename Type>inline void read(Type &xx)
Type f = 1;char ch;xx = 0;
for(ch = getchar();ch < '0' || ch > '9';ch = getchar()) if(ch == '-') f = -1;
for(;ch >= '0' && ch <= '9';ch = getchar()) xx = xx * 10 + ch - '0';
xx *= f;
void read()
template<typename T,typename ...R>void read(T &x,R &...r)
read(x);
read(r...);
int main(int argc, char** argv)
int T;read(T);
while(T--)
read(n);
printf("%d\\n",(n+1)/10);
return 0;
B
看到m <= 1000
就猜到大约是m^2
的算法,所以显然要先取模+开桶计数。把模m的和看成重量,于是转化为多重背包求是否存在方案的问题。
但麻烦的是,不能直接用dp[m][0]
,因为它受到dp[0][0] = true
的影响,必然为true;并且也无法直接算方案数。那么我们就在dp转移的过程中监听即可。
不难的一个背包居然tag是1900
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)
const int N = 1e3 + 5;
int n,m,c[N];bool dp[N*15][N];
void dbg()puts("");
template<typename T, typename... R>void dbg(const T &f, const R &... r)
cout << f << " ";
dbg(r...);
template<typename Type>inline void read(Type &xx)
Type f = 1;char ch;xx = 0;
for(ch = getchar();ch < '0' || ch > '9';ch = getchar()) if(ch == '-') f = -1;
for(;ch >= '0' && ch <= '9';ch = getchar()) xx = xx * 10 + ch - '0';
xx *= f;
void read()
template<typename T,typename ...R>void read(T &x,R &...r)
read(x);
read(r...);
void pack(int &tot,bool &ans,int v,int w)
if(!v) return;
++tot;
dwn(j,m-1,0)
dp[tot][j] = dp[tot-1][j] || dp[tot-1][(j-w+m)%m];
if(!j) ans |= dp[tot-1][(j-w+m)%m];
int main(int argc, char** argv)
read(n,m);
rep(i,1,n)
int x;read(x);c[x%m+1]++;
dp[0][0] = true;
int tot = 0;bool ans = false;
rep(i,1,m)
int u = c[i];
for(int j = 0;(1 << j) < u;++j)
pack(tot,ans,1<<j,(1<<j)*(i-1)%m);
u -= (1 << j);
pack(tot,ans,u,u*(i-1)%m);
puts(ans ? "YES" : "NO");
return 0;
C
签到。简单分类讨论。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)
const int N = 3e5 + 5;
int n;
void dbg()puts("");
template<typename T, typename... R>void dbg(const T &f, const R &... r)
cout << f << " ";
dbg(r...);
template<typename Type>inline void read(Type &xx)
Type f = 1;char ch;xx = 0;
for(ch = getchar();ch < '0' || ch > '9';ch = getchar()) if(ch == '-') f = -1;
for(;ch >= '0' && ch <= '9';ch = getchar()) xx = xx * 10 + ch - '0';
xx *= f;
void read()
template<typename T,typename ...R>void read(T &x,R &...r)
read(x);
read(r...);
int main(int argc, char** argv)
int T;read(T);
while(T--)
read(n);int s = 0;
rep(i,1,n)
int x;read(x);s += x;
if(s >= n) printf("%d\\n",s-n);
else puts("1");
return 0;
D
待填坑~
E
一看就很组合数学,而且没法dp。突破口就是令一些房间为空。于是非空的房间相当于经典的方程求解的个数问题,如果没听说过,可以参考我的这篇介绍。
枚举空房间个数i = 0~min(n-1,k)
,则C(n,i)
选出空房间,C(n-i+i-1,i)
表示n-i
个变量,和为i
的方案数,乘起来就是贡献。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)
const int N = 3e5 + 5,mod = 1e9 + 7;
int n,k;LL fac[N],ifac[N];
void dbg()puts("");
template<typename T, typename... R>void dbg(const T &f, const R &... r)
cout << f << " ";
dbg(r...);
template<typename Type>inline void read(Type &xx)
Type f = 1;char ch;xx = 0;
for(ch = getchar();ch < '0' || ch > '9';ch = getchar()) if(ch == '-') f = -1;
for(;ch >= '0' && ch <= '9';ch = getchar()) xx = xx * 10 + ch - '0';
xx *= f;
void read()
template<typename T,typename ...R>void read(T &x,R &...r)
read(x);
read(r...);
LL q_pow(LL a,LL b,LL mod)
LL ret = 1;
for(;b;b >>= 1)
if(b & 1) ret = ret * a % mod;
a = a * a % mod;
return ret;
void init(int n)
fac[0] = 1;rep(i,1,n) fac[i] = fac[i-1] * i % mod;
ifac[n] = q_pow(fac[n],mod-2,mod);
dwn(i,n-1,0) ifac[i] = (i+1) * ifac[i+1] % mod;
LL C(int x,int y)
if(x < y) return 0;
return fac[x] * ifac[y] % mod * ifac[x-y] % mod;
int main(int argc, char** argv)
read(n,k);
init(n);
int ans = 0;
rep(i,0,min(n-1,k))
ans = (ans + C(n,i) * C(n-1,i) % mod) % mod;
printf("%d\\n",ans);
return 0;
F
贪心依据是排序不等式。贪心过程需要一个数据结构,维护当前可选但未选的下标,支持插入、删除和求最小权值。这个数据结构就是优先队列。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i 以上是关于2021SCUACM集训队冬季选拔2大部分题解的主要内容,如果未能解决你的问题,请参考以下文章