T1:
题目大意:给一个串(字符集为:'a'..'z','?'),'?'代表'a'..'z'中等概率选择一个字母,问原串中期望回文子串个数。
主要思路:简单题,枚举每个子串,然后算出成为回文串的概率。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<string>
using namespace std;
string S;
double calc(int l,int r,int n){
double ans=1,ans1=0;
while (l-1>=0 && r+1<n){
if (S[l-1]!=S[r+1])
if (S[l-1]!='?' && S[r+1]!='?') return ans1;
if ((S[l-1]=='?' || S[r+1]=='?') && l-1!=r+1)
ans=ans/26;
ans1=ans1+ans;
--l;
++r;
}
return ans1;
}
class PalindromicSubstringsDiv1{
public:
double expectedPalindromes(vector <string> S1, vector <string> S2){
S="";
int n=S1.size();
for (int i=0; i<n; ++i) S+=S1[i];
n=S2.size();
for (int i=0; i<n; ++i) S+=S2[i];
double ans=0;
n=S.size();
for (int i=0; i<n; ++i){
ans+=calc(i+1,i-1,n);
ans+=calc(i+1,i,n);
}
return ans;
}
};
T2:
题目大意:给出两个数字串,每次可以将第一个的其中连续一段加一或者减一(注意,是循环的,即9+1=0),问最少对第一个串操作多少次才能变成第二个串。
主要思路:对于 第一个串s1[1..n]和 第二个串s2[1..n] ,对它们做差得到s3[1..n](只有0..9),s3[1..n]代表的既是对s3[1..n]操作把它变成全是0。对s3[1..n]做差得到s4[1..n](s4[i]=s3[i]-s3[i-1]),,显然将s3变为0就是将s4变成0,而且操作s3的区间操作就是对s4的两个不同位置的数进行操作(s4[i]+=d,s4[j]-=d),而且s4可以对任意一个数加一个任意数(但是相应的就要在其他某个数减去相应的数值),于是原问题变成 对s4的某些数增加一些值,增加的总和为D ,对s4得另一些数减去一些值,总和为-D,这样我们就可以dp了。
f[i][j]:代表前i个数字全变成0,且总共增加了j的最小代价。
最后f[n+1][0]就是答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
using namespace std;
const int MAXN=2510;
string S1,S2;
int num[MAXN],sum[MAXN];
int a1[MAXN],a2[MAXN];
int f[40000],g[40000];
const int ZERO=20000;
class CombinationLockDiv1{
public:
int minimumMoves(vector <string> P, vector <string> Q){
int n=P.size();
S1="";
for (int i=0; i<n; ++i) S1+=P[i];
n=Q.size();
S2="";
for (int i=0; i<n; ++i) S2+=Q[i];
n=S1.size();
for (int i=0; i<n; ++i) num[i]=S1[i]-S2[i];
for (int i=1; i<=n; ++i) sum[i]=num[i]-num[i-1];
sum[0]=num[0];
if (n==0) return 0;
for (int i=0; i<=n; ++i){
while (sum[i]<0) sum[i]+=10;
while (sum[i]>10) sum[i]-=10;
a1[i]=10-sum[i];
a2[i]=sum[i];
}
memset(f,63,sizeof(f));
f[ZERO-a1[0]]=a1[0];
f[ZERO+a2[0]]=a2[0];
for (int i=0; i<n; ++i){
memset(g,63,sizeof(g));
for (int j=0; j<40000; ++j){
if (j-a1[i+1]>=0) g[j-a1[i+1]]=min(g[j-a1[i+1]],f[j]+a1[i+1]);
if (j+a2[i+1]<40000) g[j+a2[i+1]]=min(g[j+a2[i+1]],f[j]+a2[i+1]);
}
memcpy(f,g,sizeof(f));
}
//for (int i=0; i<=n; ++i) printf("%d %d\n",a1[i],a2[i]);
return f[ZERO]/2;
}
};