2019牛客暑期多校训练营(第五场)
题号 | 标题 | 已通过代码 | 题解/讨论 | 通过率 | 团队的状态 |
---|---|---|---|---|---|
A | digits 2 | 点击查看 | 进入讨论 | 1016/2378 | 通过 |
B | generator 1 | 点击查看 | 进入讨论 | 513/3524 | 通过 |
C | generator 2 | 点击查看 | 进入讨论 | 34/592 | 已补 |
D | generator 3 | 点击查看 | 进入讨论 | 4/23 | 未通过 |
E | independent set 1 | 点击查看 | 进入讨论 | 36/98 | 队友已补 |
F | maximum clique 1 | 点击查看 | 进入讨论 | 77/779 | 队友已补 |
G | subsequence 1 | 点击查看 | 进入讨论 | 494/2432 | 通过 |
H | subsequence 2 | 点击查看 | 进入讨论 | 278/1311 | 通过 |
I | three points 1 | 点击查看 | 进入讨论 | 125/2614 | 未通过 |
J | three points 2 | 点击查看 | 进入讨论 | 4/70 | 队友已补 |
lwqtql:https://www.cnblogs.com/lwqq3/
zgtql:http://brotherzhi.com/
A
#include <bits/stdc++.h>
using namespace std;
int T;
int n;
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++)printf("%d",n);
puts("");
}
return 0;
}
B
矩阵快速幂
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod;
struct node {
ll c[2][2];
};
node mul(node x, node y) {
node res;
memset(res.c, 0, sizeof(res.c));
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)
for(int k = 0; k < 2; k++)
res.c[i][j] = (res.c[i][j] + x.c[i][k] * y.c[k][j] % mod) % mod;
return res;
}
node pow_mod(node x, ll y) {
node res;
res.c[0][0] = res.c[1][1] = 1LL;
res.c[0][1] = res.c[1][0] = 0LL;
while(y) {
if(y & 1) res = mul(res, x);
x = mul(x, x);
y >>= 1;
}
return res;
}
char s[1000005];
int ss[1000005];
int main() {
ll x0, x1, a, b;
cin>>x0>>x1>>a>>b;
scanf("%s", s + 1);
int len = strlen(s + 1);
for(int i = 1; i <= len; i++) ss[i] = s[i] - '0';
cin>>mod;
node A;
A.c[0][0] = a;
A.c[0][1] = b;
A.c[1][0] = 1LL;
A.c[1][1] = 0LL;
if(len == 1) {
if(s[1] == '1') {
printf("%lld
", x1);
return 0;
}
}
ss[len]--;
for(int i = len; i >= 1; i--) {
if(ss[i] < 0) {
ss[i] += 10;
ss[i - 1]--;
}
}
node now;
now.c[0][0] = now.c[1][1] = 1LL; now.c[0][1] = now.c[1][0] = 0LL;
for(int i = 1; i <= len; i++) {
now = pow_mod(now, 10);
int t = ss[i];
node pp = pow_mod(A, 1LL * t);
now = mul(now, pp);
}
ll ans = now.c[0][0] * x1 % mod + now.c[0][1] * x0 % mod;
ans %= mod;
printf("%lld
", ans);
return 0;
}
C
写了篇题解https://www.cnblogs.com/1625--H/p/11291238.html
BSGS
E
位元状压DP
#include <bits/stdc++.h>
using namespace std;
char dp[1 << 26];
int adj[30];
int main() {
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
adj[u] |= (1 << v);
adj[v] |= (1 << u);
}
for(int i = 0; i < n; i++) adj[i] = (~adj[i]), adj[i] ^= (1 << i);
//puts("??");
for(int i = 1; i < (1 << n); i++) {
int t = __builtin_ctz(i);
dp[i] = max(dp[i - (1 << t)], (char)(dp[i & adj[t]] + 1));
}
int ans = 0;
for(int i = 1; i < (1 << n); i++) ans += dp[i];
printf("%d
", ans);
return 0;
}
G
思路跟标程反了。一直没调对,不知道那里出错了。
下面是按照标程思路写的。思路也不是很难,如果按照长度等不等区分开来进行DP的话,就要额外维护一个东西。
#include <bits/stdc++.h>
using namespace std;
const int N = 3030;
const int mod = 998244353;
typedef long long ll;
char s[N],t[N];
int n,m;
ll d[N][N],C[N][N];
void predo(){
C[0][0] = 1;
for(int i=1;i<N;i++){
C[i][0] = 1;
for(int j=1;j<N;j++)
C[i][j] = (C[i-1][j] + C[i-1][j-1])%mod;
}
}
void add(ll &x,ll y){x = (x + y)%mod;}
void DP(){
for(int i=0;i<=n;i++)d[i][0] = 1;
for(int i=0;i<=n;i++)if(s[i] == t[1])d[i][1] = 1;
for(int j=2;j<=m;j++){
ll sum = 0;
for(int i=1;i<=n;i++){
if(s[i] == t[j])
add(d[i][j],sum);
add(sum,d[i][j-1]);
}
}
}
int main(){
int tt;scanf("%d",&tt);
predo();
while(tt--){
scanf("%d%d",&n,&m);
scanf("%s%s",s+1,t+1);
ll res = 0;
for(int i=0;i<=n+1;i++)for(int j=0;j<=n+1;j++)d[i][j] = 0;
DP();
for(int i=1;i<=n;i++)
if(s[i]!='0')
for(int j=m;j<=(n-i);j++)
add(res,C[n-i][j]);
for(int j=m;j>=1;j--){
ll sum = j == 1;
for(int i=1;i<=n;i++){
if(s[i] > t[j])
add(res,sum * C[n-i][m-j]);
if(j>1)add(sum,d[i][j-1]);
}
}
cout<<res<<endl;
}
return 0;
}
H
对于每两个字母,都能知道单个字符前面有多少个别类字符,所有的情况加起来后就知道前面总共有多少个字符了。不可能的情况可能出现在
- 两次输入中,同一类型字母个数不同
- 总个数不够n个
- 两个字符位置相同
- 有地方空着,或者填入了超出n的位置
#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
int num[20][10010];
int tot[20];
int n,m;
char s[N];
char ans[10*N];
int main(){
scanf("%d%d",&n,&m);
bool flag = true;
for(int i=1;i<=m*(m-1)/2;i++){
char a,b;
int len;
cin>>a>>b;scanf("%d",&len);
if(len == 0){
getchar();continue;
}
scanf("%s",s);
int cnta = 0,cntb = 0;
for(int i=0;i<len;i++){
if(s[i] == a)cnta++,num[a-'a'][cnta] += cntb;
if(s[i] == b)cntb++,num[b-'a'][cntb] += cnta;
}
//判断个数与之前是否一致
if(tot[a-'a'] == 0){
tot[a-'a'] = cnta;
}
else if(tot[a-'a'] != cnta){
flag = false;
}
if(tot[b-'a'] == 0){
tot[b-'a'] = cntb;
}
else if(tot[b-'a'] != cntb){
flag = false;
}
}
for(int i=0;i<m;i++){
for(int j=1;j<=tot[i];j++){
//判断是否有重位,或者位置范围超出n
if(ans[num[i][j] + j-1] != 0 || num[i][j] + j-1 >= n){
flag = false;break;
}
ans[num[i][j] + j-1] = 'a'+i;
}
if(!flag)break;
}
int sum = 0;for(int i=0;i<m;i++)sum += tot[i];
if(sum != n)flag = false;
ans[sum] = ' ';
if(flag)printf("%s
",ans);
else printf("-1");
return 0;
}