Topcoder SRM 607 div1题解
好久没来写了,继续继续。。。
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题解的更多相关文章
- Topcoder SRM 602 div1题解
打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...
- Topcoder SRM 608 div1 题解
Easy(300pts): 题目大意:有n个盒子,一共有S个苹果,每个盒子有多少个苹果不知道,但是知道每个盒子的苹果下限和上限.现在要至少选择X个苹果,问如果要保证无论如何都能获得至少X个苹果,至少需 ...
- Topcoder SRM 606 div1题解
打卡! Easy(250pts): 题目大意:一个人心中想了一个数,另一个人进行了n次猜测,每一次第一个人都会告诉他实际的数和猜测的数的差的绝对值是多少,现在告诉你所有的猜测和所有的差,要求你判断心中 ...
- Topcoder SRM 605 div1 题解
日常打卡- Easy(250pts): 题目大意:你有n种汉堡包(统统吃掉-),每一种汉堡包有一个type值和一个taste值,你现在要吃掉若干个汉堡包,使得它们taste的总和*(不同的type值的 ...
- Topcoder SRM 604 div1题解
CTSC考完跑了过来日常TC--- Easy(250pts): 题目大意:有个机器人,一开始的位置在(0,0),第k个回合可以向四个方向移动3^k的距离(不能不动),问是否可以到达(x,y),数据满足 ...
- Topcoder SRM 603 div1题解
昨天刚打了一场codeforces...困死了...不过赶在睡前终于做完了- 话说这好像是我第一次做250-500-1000的标配耶--- Easy(250pts): 题目大意:有一棵树,一共n个节点 ...
- Topcoder SRM 601 div1题解
日常TC计划- Easy(250pts): 题目大意:有n个篮子,每个篮子有若干个苹果和橘子,先任取一个正整数x,然后从每个篮子中选出x个水果,把nx个水果放在一起,输出一共有多少种不同的组成方案.其 ...
- Topcoder SRM 600 div1题解
日常TC计划正式启动! Easy(250pts): 题目大意:给你一个集合,里面一堆数,初始数为0,给你一个目标数,你可以选择集合中若干个数进行OR操作来得到目标数.问至少删去多少个数,使得你永远无法 ...
- Topcoder SRM 643 Div1 250<peter_pan>
Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...
随机推荐
- spring boot 中文文档地址
spring boot 中文文档地址 http://oopsguy.com/documents/springboot-docs/1.5.4/index.html Spring Boot 参考指 ...
- 【数据库】 SQLite 语法
[数据库] SQLite 语法 一 . 创建数据库 1. 只需创建数据库,只需创建文件,操作时将连接字符串指向该文件即可 2. 连接字符串 : data source = FilePath; 不能加密 ...
- 【数据库】 SQL 使用注意点
[数据库] SQL 使用注意点 一. 索引 1. 常用的搜索条件,都建议加上索引,但状态列除外(该列只有0,1或几个值,不需要加索引,因为没效果) 2. 查询时, 索引列不能做函数处理,会不走索引 3 ...
- model的index无限次数执行导致stackOverFlow
model的index无限次数执行导致stackOverFlow
- Android TextView 单行文本的坑
这是android系统的一个bug,描述如下:https://code.google.com/p/android/issues/detail?id=33868 具体来说就是当一个TextView设置了 ...
- html5判断设备的动作
相应的事件 deviceorientation事件提供设备的物理方向信息,表示为一系列本地坐标系的旋角. devicemotion事件提供设备的加速信息,表示为定义在设备上的坐标系中的卡尔迪坐标.其还 ...
- 6.0 实现app登录
1.0.0:学习ui自动化准备工作 待测app,我这里有准备两个apk,这两个都是我曾经做过的项目,后续的文章都是基于这两个app! 链接:https://pan.baidu.com/s/1I0vR9 ...
- 维特比算法(Viterbi)及python实现样例
维特比算法(Viterbi) 维特比算法 维特比算法shiyizhong 动态规划算法用于最可能产生观测时间序列的-维特比路径-隐含状态序列,特别是在马尔可夫信息源上下文和隐马尔科夫模型中.术语“维特 ...
- cmp快排 结构体快排
由于深陷于JAVA的面向对象思想,常常会用到结构体,记一下这个模板,方便直接调用进行结构体排序: struct point { int val,turn; }; bool cmp(struct poi ...
- DFS(4)——hdu1010Tempter of the Bone
一.题目回顾 题目链接:Tempter of the Bone Problem Description The doggie found a bone in an ancient maze, whic ...