掉大分日常xD
A .Password
题意
Monocarp有个密码,密码长度四位,只有两种数字(0~9)组成,每种数字出现两次,给你没有出现的数字序列(长度为n),问密码有多少种可能
思路
非常简单的数学题,有10-n种数字会出现,从中选两个为C (10-n,2)再✖C(4,2)即为答案
代码
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
int x; cin>>x;
}
cout<<((10-n)*(9-n))/2*6<<endl;
}
int main()
{
int tt;
cin>>tt;
while(tt--)
solve();
}
B. Permutation Value
题意
构造一个长度为n的序列,定义这个序列的值为序列的子段仍然是一个序列的数量,要求最小化这个值
思路
非常简单的构造题,显而易见答案最少恒为2(1和序列本身)直接形如1,3,5,4,2这种方式生成序列即可
代码
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n;
cin>>n;
vector<int>res(n+1);
int st=1,ed=n;
for(int i=1;i<=n;i++)
{
if(i&1) res[st++]=i;
else res[ed--]=i;
}
for(int i=1;i<=n;i++) cout<<res[i]<<" ";
cout<<endl;
}
int main()
{
int tt;
cin>>tt;
while(tt--)
solve();
}
C.Save the magizines
题意
有n个盒子,每个盒子里有a[i]本杂志,给一个字符串s,只有1和0构成,分别代表第i个盒子上是否有盖子,有盖子的盒子中的杂志不会被淋湿,你可以把每个盖子从i移动到i-1(每个盖子仅能被移动一次)问最后不被淋湿的杂志最多有多少本
思路1
一眼dp,但是没想出来 还是靠大佬指点才想到,设dp[i][1/0]表示第i个位置是否有盖子,可以得到如下转移
s[i]=='1'
dp[i][1] = max(dp[i-1][0] , dp[i-1][1]) + a[i] ;
dp[i][0] = dp[i-1][0] + a[i-1];
s[i]=='0'
dp[i][0] = max(dp[i-1][0] , dp[i-1][1])
代码(dp)
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int dp[maxn][2];
void solve()
{
int n;
scanf("%d",&n);
string s;
cin >> s; s=" "+s;
vector<int> a(n+1);
dp[0][0] = dp[0][1] = 0;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
dp[i][0] = dp[i][1] = 0;
}
for (int i = 1; i <= n; i++)
{
if (s[i] == '1')
{
dp[i][1] = max(dp[i - 1][1]+a[i], dp[i - 1][0]+a[i]);
dp[i][0] = dp[i - 1][0] + a[i - 1];
}
else
dp[i][0] = max(dp[i - 1][1], dp[i - 1][0]);
}
printf("%d\n",max(dp[n][0],dp[n][1]));
}
int main()
{
int tt;
scanf("%d",&tt);
while (tt--)
solve();
return 0;
}
思路2
可以看到,对于每一段连续的1,假设这段为(i ~ j),那我们通过调整盖子,这一段1中最多出现一个0,那么如何确定这个0的位置呢?考虑什么情况下需要产生这个0,当a[i-1]可以替换掉这段1中的某个值使得sum增大时就调个0出来,换句话说就是找每段连续的1里面最小值和a[i-1]判断即可
代码
代码思路参考jls,orz
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int maxn=2e5+10;
const int INF=0x3f3f3f3f;
int dp[maxn][2];
void solve()
{
int n;
scanf("%d",&n);
string s;
cin >> s; s=" "+s;
vector<int> a(n+1),sum(n+1);
for (int i = 1; i <= n; i++)
cin >> a[i];
int ans=0;
for(int i=1,j=0;i<=n;i++)
{
if(s[i]=='0')
j = i;//找1前的首个0
else if(j && a[j] > a[i])//在连续的1种找最小的满足条件的那个
{
swap(s[i],s[j]);
j = i;
}
}
for(int i=1;i<=n;i++)
if(s[i]=='1')
ans+=a[i];
cout<<ans<<endl;
}
int main()
{
int tt;
cin >> tt;
while (tt--)
solve();
return 0;
}