B. Boy and Girls
题意:给一串含有n个Gn个B的字符串, 交换相邻字符,使字符串达到GBGBGB / BGBGBG,求最小交换次数;
解法:暴力扫字符串,出现不满足条件的情况,就在后边找到相应的字符。O(n^2)绝对超时;因此,不能扫。换一个思路,从末状态开始入手,每一个B/G都要到达位置1,3,5,7,9 / 2,4,6,8,10,而将一个字符从位置x1移动到x2,需要交换|x1-x2|次,因此只需计算|x1-1|+|x2-3|+|x3-5|+...+|xn-2*n+1|和|x1-2|+|x2-4|+|x3-6|+...+|xn-2*n|,取最大值即可
#include <cstdio>
#include<queue>
#include<cstdlib>
#define ll long long
using namespace std;
ll T,n;
char s[200005];
queue<ll> q;
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld",&n);
scanf(" %s",s);
for(int i=0;i<2*n;i++)
{
if(s[i]=='B')
{
q.push(i);
}
}
ll k1=0,k2=1,sum1=0,sum2=0;
while(!q.empty())
{
ll x=q.front();
q.pop();
sum1+=abs(k1-x);
sum2+=abs(k2-x);
k1+=2;
k2+=2;
}
printf("%lld\n",min(sum1,sum2));
}
return 0;
}
E.Colorful Ribbon
题目类型:dp
题意:将给定只包含小写字符的字符串,分为没有重复的几段,问有多少种分法
解法:dp[i]表示前i个字符可以分为几段,转移方程为dp{i}=sum(dp[k]) (k = p ~ i-1 ),p表示当前串,上一个断点能取到的中,最靠前的那个字符的位置
#include <iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f3f3f;
int T,vist[30],p;
ll dp[100005];
char s[100005];
const ll MOD = 1000000000+7;
int main()
{
scanf("%d",&T);
while(T--)
{
memset(s,0,sizeof(s));
scanf(" %s",s+1);
memset(dp,0,sizeof(dp));
int len = strlen(s+1);
memset(vist,0,sizeof(vist));
dp[0]=1;
p=-1;
for(int i=1;i<=len;i++)
{
p=max(vist[s[i]-'a'],p);
for(int j=p;j<i;j++)
{
dp[i]+=(dp[j]%MOD);
}
vist[s[i]-'a']=i;
}
cout << dp[len]%MOD << endl;
}
return 0;
}
J.Repeated String
题意:构造长度为n的B,使得与A的distance最小;
题解:暴力枚举a-z,判断每一位的B上的字母应该是什么。O(26*n*m)
Code:(不知道为啥RE,然后又TE,以后知道哪错了,就补代码)
L.QAQ Number
题意:计算出指定范围内,符合条件的数字的个数
题解:现场想法是利用10^0-10^3有90个,10^6-10^9有90个.....10^15-10^18有90个,将完全包含的区间加上去,左右边界单独处理,处理时发现,右边界数量级很大,不能个暴力,然后队友想了个判断方法,异常难写啊。。。最后,这写法估计要代码200+。。。放弃了。下场才知道,这个神奇做法。
因为,通过检测方法实现数量很大,所以说明在给定范围的答案不多,因此直接从答案入手,枚举Q,B即可,可以利用;有个小问题:就是B为0的时候,方法1。特判B为0,00,000...时,方法2,vist[]标记这个数是否被访问过;
#include <cstdio>
#include<queue>
#include<cstdlib>
#define ll long long
using namespace std;
ll T,n;
char s[200005];
queue<ll> q;
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld",&n);
scanf(" %s",s);
for(int i=0;i<2*n;i++)
{
if(s[i]=='B')
{
q.push(i);
}
}
ll k1=0,k2=1,sum1=0,sum2=0;
while(!q.empty())
{
ll x=q.front();
q.pop();
sum1+=abs(k1-x);
sum2+=abs(k2-x);
k1+=2;
k2+=2;
}
printf("%lld\n",min(sum1,sum2));
}
return 0;
}