好久没来写了,继续继续。。。

Easy(250pts):

//前方请注意,样例中带有zyz,高能预警。。。

题目大意:给你一个字符串,中间有一些是未知字符,请你求出这个字符串的回文子串个数的期望值。数据满足字符最多2500个。

我们考虑每一个子串,它对答案的贡献度就是它是回文串的概率,那么我们扫一遍就可以了,

这样做时间复杂度O(n^3),显然过不去。

我们考虑一下对于一个子串,在判断其是回文串的时候,我们一定是从中间往两边扫的,那么其实中间这些子串我们已经统计过答案了,

也就是说,我们通过枚举中间点来统计答案就可以了,

时间复杂度O(n^2),代码如下:

 #include <bits/stdc++.h>
using namespace std;
string s;
double ans=0.0;
int n;
class PalindromicSubstringsDiv1
{
public:
double expectedPalindromes(vector <string> S1, vector <string> S2)
{
for (int i=;i<S1.size();i++) s+=S1[i];
for (int i=;i<S2.size();i++) s+=S2[i];
n=s.length();
for (int i=;i<n;i++)
{
//i means the middle point of the substring
double now=1.0;
int lx=i-,rx=i+;
while (lx>=&&rx<n)
{
if (s[lx]=='?'&&s[rx]=='?') now=now*1.0/26.0;
else if (s[lx]!='?'&&s[rx]!='?'&&s[lx]==s[rx]) now=now*1.0;
else if (s[lx]!='?'&&s[rx]!='?') now=0.0;
else now=now*1.0/26.0;
ans+=now;
--lx;++rx;
}
now=1.0,lx=i,rx=i+;
while (lx>=&&rx<n)
{
if (s[lx]=='?'&&s[rx]=='?') now=now*1.0/26.0;
else if (s[lx]!='?'&&s[rx]!='?'&&s[lx]==s[rx]) now=now*1.0;
else if (s[lx]!='?'&&s[rx]!='?') now=0.0;
else now=now*1.0/26.0;
ans+=now;
--lx,++rx;
}
}
ans+=1.0*n;
return ans;
}
};

Medium(475pts):

题目大意:有一串数字(0~9)围成了一个环,每一次可以选取一段区间,然后同时+1或者-1,(0 -1变成了9,9 +1变成了0)求现在到目标的最少操作次数。数据满足最多2500个元素。

这题怎么就475分了啊。。。感觉这么难。。。

容易观察到,结果只在%10意义下有用,所以先处理出差%10的余数。

接下来需要一个观察:如果两个区间一个是+操作,一个是-操作,那么一定可以做到这两个区间不相交。

然后考虑dp,f[i][j][k]表示当前在第i位,区间已经改变了j,而k则代表是+操作还是-操作。

这样时间复杂度是O(n^3)的,可以通过div2那个题。

然后我就跑去看官方题解了,然后没看懂。。。

大概的感受就是,观察出其实一个区间的操作改变不会很多,就只有-10~10以内,然后判一下就好了。

时间复杂度O(n^2),带一个常数,代码如下:

 #include <bits/stdc++.h>
#define Maxn 2507
#define Maxm 5507
#define inf 200000007
using namespace std;
string S,T;
int n;
int d[Maxn];
int f[Maxn][Maxm][];
bool vis[Maxn][Maxm][];
class CombinationLockDiv1
{
int tryit(int pos, int x, int dir)
{
//pos means which number it is dealing with now
//x means the addition of the interval
//dir means the interval is to add or to minus
if (vis[pos][x][dir]) return f[pos][x][dir];
vis[pos][x][dir]=true;
if (pos==n)
{
f[pos][x][dir]=;
return f[pos][x][dir];
}
f[pos][x][dir]=inf;
for (int newdir=;newdir<=;newdir++)
{
for (int y=max(x-,);y<=min(x+,);y++)
{
if (newdir==&&((d[pos]-y%+)%!=)) continue;
if (newdir==&&((d[pos]+y)%!=)) continue;
int z;
if (newdir!=dir) z=y; else z=max(y-x,);
f[pos][x][dir]=min(f[pos][x][dir],z+tryit(pos+,y,newdir));
}
}
return f[pos][x][dir];
};
public:
int minimumMoves(vector <string> P, vector <string> Q)
{
for (int i=;i<P.size();i++) S+=P[i];
for (int i=;i<Q.size();i++) T+=Q[i];
n=S.size();
for (int i=;i<n;i++) d[i]=(S[i]-T[i]+)%;
memset(vis,false,sizeof(vis));
memset(f,,sizeof(f));
return tryit(,,);
}
};

Hard(1000pts):

题目大意:有n个轮子,半径间隔完全相等地一横排排在一条直线上,有个起点和终点完全对称(到最近的轮子距离也相同,也在x轴上),现在有根绳子,可以任意地从S开始环绕轮子,然后到T。这样的绳子显然有无数多条,给定k,求第k短的长度。数据满足n<=50,k<=10^18。

这题的第一步非常难,也非常关键。(然而cyand1317表示并不难。。。)

所有的绳子都可以划分成四种的拼凑,第一种是从起点到上半部分,第二种是轮子的上半部分到下一个轮子的上半部分,第三种是轮子的上半部分到下一个轮子的下半部分,第四种是包围一个轮子半圈(轮子的上半部分到轮子的下半部分)。

然后我们发现,第一种对于所有绳子都恰好有两段,于是我们只需要考虑后三段就可以了,表示成一个三元组(x,y,z)。

我们先dp预处理出每一个状态的方案数,我们需要四维x,y,z以及一个数字表示方向。

然而实际上不需要,第四种情况的奇偶性就可以判断方向,然后直接O(n^3)的dp就可以了,

最后我们需要二分答案,然后来判定。

需要注意的是,本题数据这么大,显然是存不下的,我们需要设定一个inf,当数大于inf的时候,直接不参与计算。

时间复杂度O(n^3),代码如下:

 #include <bits/stdc++.h>
#define inf (1LL<<60)
using namespace std;
double A,B,R;
int n;
long long combination[][];
long long f[][][][];
class PulleyTautLine
{
long long calc(long long n, long long k)
{
k=min(k,n-k);
if (k==) return ;
if (k==) return n;
if (k==&&0.5*n*(n-)<1.1*inf) return 1LL*n*(n-)/;
if (k==&&1.0/*n*(n-)*(n-)<1.1*inf) return 1LL*n*(n-)*(n-)/;
if (k<&&n<) return combination[n][k];
return inf;
}
long long tryit(double len)
{
long long res=;
for (int i=;i<;i++)
for (int j=;j<;j++)
{
//number of moves A&B
//number of moves R
if (f[i][j][n-][]>)
{
for (int k=;k<=i;k++)
{
//number of moves A
double L=k*A+(i-k)*B+j*R;
if (L>len) continue;
//max number of circles
long long cir=(long long)((len-L)/2.0/R);
long long cnt1=calc(i,k),cnt2=calc(cir+i+,i+);
if (cnt2>inf/cnt1/f[i][j][n-][]) return inf;
res+=1LL*cnt1*cnt2*f[i][j][n-][];
if (res>inf) return inf;
}
}
}
return res;
}
public:
double getLength(int d, int r, int N, long long k)
{
n=N;
A=d,B=sqrt((double)d*d-4.0*r*r)+2.0*r*asin(2.0*r/d),R=r*acos(-1.0);
double L=sqrt((double)d*d-(double)r*r)+r*asin((double)r/d);
if (n==) return (k-)/*2.0*R+2.0*L;
memset(combination,,sizeof(combination));
for (int i=;i<=;i++)
{
combination[i][]=;
for (int j=;j<=;j++)
combination[i][j]=min(inf,combination[i-][j]+combination[i-][j-]);
}
memset(f,,sizeof(f));
f[][][][]=;
for (int i=;i<;i++)
for (int j=;j<;j++)
for (int k=;k<n;k++)
for (int p=;p<=;p++)
{
//there are three kinds of moves
//one is to change the direction
//the other two are move forward (become nearer or farer)
if (p==) f[i][j+][k][]=min(inf,f[i][j+][k][]+f[i][j][k][p]);
if (j%==&&k<n-) f[i+][j][k+][]=min(inf,f[i+][j][k+][]+f[i][j][k][p]);
if (j%==&&k>) f[i+][j][k-][]=min(inf,f[i+][j][k-][]+f[i][j][k][p]);
}
double left=0.0,right=1000.0*A,mid;
for (int i=;i<=;i++)
{
mid=(double)(left+right)/;
if (tryit(mid)>=k) right=mid; else left=mid;
}
return mid+2.0*L;
}
};

Topcoder SRM 607 div1题解的更多相关文章

  1. Topcoder SRM 602 div1题解

    打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...

  2. Topcoder SRM 608 div1 题解

    Easy(300pts): 题目大意:有n个盒子,一共有S个苹果,每个盒子有多少个苹果不知道,但是知道每个盒子的苹果下限和上限.现在要至少选择X个苹果,问如果要保证无论如何都能获得至少X个苹果,至少需 ...

  3. Topcoder SRM 606 div1题解

    打卡! Easy(250pts): 题目大意:一个人心中想了一个数,另一个人进行了n次猜测,每一次第一个人都会告诉他实际的数和猜测的数的差的绝对值是多少,现在告诉你所有的猜测和所有的差,要求你判断心中 ...

  4. Topcoder SRM 605 div1 题解

    日常打卡- Easy(250pts): 题目大意:你有n种汉堡包(统统吃掉-),每一种汉堡包有一个type值和一个taste值,你现在要吃掉若干个汉堡包,使得它们taste的总和*(不同的type值的 ...

  5. Topcoder SRM 604 div1题解

    CTSC考完跑了过来日常TC--- Easy(250pts): 题目大意:有个机器人,一开始的位置在(0,0),第k个回合可以向四个方向移动3^k的距离(不能不动),问是否可以到达(x,y),数据满足 ...

  6. Topcoder SRM 603 div1题解

    昨天刚打了一场codeforces...困死了...不过赶在睡前终于做完了- 话说这好像是我第一次做250-500-1000的标配耶--- Easy(250pts): 题目大意:有一棵树,一共n个节点 ...

  7. Topcoder SRM 601 div1题解

    日常TC计划- Easy(250pts): 题目大意:有n个篮子,每个篮子有若干个苹果和橘子,先任取一个正整数x,然后从每个篮子中选出x个水果,把nx个水果放在一起,输出一共有多少种不同的组成方案.其 ...

  8. Topcoder SRM 600 div1题解

    日常TC计划正式启动! Easy(250pts): 题目大意:给你一个集合,里面一堆数,初始数为0,给你一个目标数,你可以选择集合中若干个数进行OR操作来得到目标数.问至少删去多少个数,使得你永远无法 ...

  9. Topcoder SRM 643 Div1 250<peter_pan>

    Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...

随机推荐

  1. js 实现字符串转日期进行比较大小

    代码如下 var a = '2016-01-01 12:12:12'; var b = '2016-01-01 12:12:13'; var al = new Date(a).getTime(); v ...

  2. Microsoft Security Essentials 和 Windows Defender 离线升级包下载地址

    自从微软提供了免费的杀毒软件之后我就卸载掉了其他的杀毒软件.但是最近遇到了个小问题,我这里有一批电脑不能联网,杀毒软件的升级成了问题.在网上搜索了一番,终于找到了官方的离线升级包下载地址.放在这里备用 ...

  3. cloudera manager服务迁移(scm数据库在postgresql上,其他amon,rman,oozie,metastore等在mysql上)

    公司线上大数据集群,之前用的是公有云主机,现在换成了自己idc机房机器,需要服务迁移,已下为测试: 1.备份原postgresql数据库: pg_dump -U scm scm > scm.sq ...

  4. Android开发免费类库和工具集合

    用于Android开发的免费类库和工具集合,按目录分类. Action Bars ActionBarSherlock Extended ActionBar FadingActionBar GlassA ...

  5. 【python模块】——logging

    python学习——logging模块

  6. 【赛后补题】(HDU6223) Infinite Fraction Path {2017-ACM/ICPC Shenyang Onsite}

    场上第二条卡我队的题目. 题意与分析 按照题意能够生成一个有环的n个点图(每个点有个位数的权值).图上路过n个点显然能够生成一个n位数的序列.求一个最大序列. 这条题目显然是搜索,但是我队在场上(我负 ...

  7. C++学习009预处理器指令符号 # ## #@ 符号的使用

    # ## #@ 符号是预处理器指令符号. 当预处理器遇到#指令符号时,会将#之后的部分用双引号括起来 当预处理去遇到##指令符号时,直接将##前后部分连接起来 当预处理器遇到#@指令符号,将#@之后的 ...

  8. Django入门与实战

    第1章 介绍课程目标及学习内容 1-1 课程介绍: 第2章 课前准备 2-1 课前准备: 第3章 开发环境搭建 3-1 开发环境搭建: 第4章 创建项目及应用 4-1 创建项目,并了解项目目录下的部分 ...

  9. (原创)像极了爱情的详解排序二叉树,一秒get

    排序二叉树(建立.查找.删除) 二叉树我们已经非常熟悉了,但是除了寻常的储存数据.遍历结构,我们还能用二叉树做什么呢? 我们都知道不同的遍历方式会对相同的树中产生不同的序列结果,排序二叉树就是利用二叉 ...

  10. cmd命令笔记

    查看端口信息:netstat -ano eg. netstat -ano|findstr 0.0.0.0:443 根据pid查看进程信息等:wmic process get name,executab ...