前言:

img

牛客周赛 Round 42

A

模拟

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;
cin>>s;
if(s.length()>1)
cout<<"kou";
else
{
cout<<"yukari";
}
}

B

模拟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e6+100;
ll a[N];
const int mod=1e9+7;
int main()
{
ll ans=0;
int n;
cin>>n;
int l=0;
string s;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
cin>>s;
int i=1;
for(auto c:s)
{
if(c=='R')
{
if(i+1==n+1)
{
ans+=a[i];
ans%=mod;
continue;
}
i++;
ans+=a[i];
ans%=mod;
}
else
{
if(i-1==0)
{
ans+=a[i];
ans%=mod;
continue;
}
i--;
ans+=a[i];
ans%=mod;
}
}
cout<<ans%mod;
}

C

偶数的话分开乘法,奇数的话取出最大的不要,其他分开乘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e6+100;
ll a[N];
ll b[N];
int main()
{
//其实就是素数要怎么乘法的问题啦
//最大跟最小的差最小
//感觉是分类讨论
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
ll maxn=0;
ll minn=1e18;
if(n%2)
{
maxn=a[n];
minn=a[n];
for(int i=1;i<=n/2;i++)
{
maxn=max(maxn,a[i]*a[n-i]);
minn=min(minn,a[i]*a[n-i]);
}
cout<<maxn-minn;
return 0;
}
for(int i=1;i<=n/2;i++)
{
maxn=max(maxn,a[i]*a[n-i+1]);
minn=min(minn,a[i]*a[n-i+1]);
}
cout<<maxn-minn;
}

D

树形dp

子树返回上来的时候如果子树大小是偶数,就切掉这条边即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
vector<ll>a[100005];
int sz[100005];
ll ans=0;
void dfs(int x,int fa){
sz[x] = 1;
for(auto to : a[x]){
if(to == fa) continue;
dfs(to,x);
if(sz[to] % 2 == 0)
ans++;
sz[x] += sz[to];
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
while(t--){
int n;
cin>>n;
int m=n-1;
while(m--){
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
if(n&1){
cout<<-1;
}
else{
dfs(1,0);
cout<<ans;
}
}
return 0;
}

E

组合数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<bits/stdc++.h>
using namespace std;
long long C[1010][1010];
long long pow10[101010];
int mod=1e9+7;
int main(){
int n,i,j,k;
for(i=0;i<=1000;i++){
for(j=0;j<=i;j++){
if(j==0||j==i)C[i][j]=1;
else C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
pow10[0]=1;
for(i=1;i<=1000;i++)pow10[i]=pow10[i-1]*10%mod;
cin>>n>>k;
string s;
cin>>s;
long long ans=0;
for(i=0;i<n;i++)
{
for(j=0;j<k;j++)
{
ans+=pow10[k-j-1]*(s[i]-'0')%mod*C[i][j]%mod*C[n-1-i][k-1-j]%mod;
ans%=mod;
}
}
cout<<ans<<'\n';
}

F

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
dp[i][j]表示从已经有i个2,j个3的状态,到至少有a个2,b个3的期望投掷次数

(i,j)==(a,b) 时 dp[i][j]=0

i==a,可以列出转移方程

dp[i][j]= 1/3 * dp[i][j] + 1/3 * dp[i][j] + 1/3 * dp[i][j+1] + 1 (三个式子分别表示丢123,丢1没贡献,丢2我已经有a个2了,也相当于没贡献)

移项得 dp[i][j] = dp[i][j+1] + 3

类似的 j==b时,有 dp[i][j] = dp[i+1][j] +3

其他情况

dp[i][j] = 1/3 * dp[i][j] + 1/3 * dp[i+1][j] + 1/3 * dp[i][j+1] + 1

移项得 dp[i][j] = (dp[i+1][j]+dp[i][j+1]+3)/2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
int mod=1e9+7;
ll pows(ll a,ll n)
{
ll ans=1;
while(n)
{
if(n&1)
{
ans=ans*a%mod;
}
a=a*a%mod;
n>>=1;
}
return ans;
}
signed main(){
int X;
cin >> X;
int p = 0, q = 0;
while (X % 2 == 0) X /= 2, p++;
while (X % 3 == 0) X /= 3, q++;
if (X != 1) {
cout<<-1;
return 0;
}
int dp[p+5][q+5];
for(int i=0;i<=p;i++){
for(int j=0;j<=q;j++){
dp[i][j]=0;
}
}
for(int i=p;i>=0;i--)for(int j=q;j>=0;j--){
if (i == p && j == q) continue;
if (i == p) {
dp[i][j] = dp[i][j + 1] + 3;
} else if (j == q) {
dp[i][j] = dp[i + 1][j] + 3;
} else {
dp[i][j] = (dp[i + 1][j] + dp[i][j + 1] + 3) *pows(2,mod-2);
}
dp[i][j]%=mod;
}
cout<<dp[0][0];
return 0;
}