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*... ...
随机推荐
- 解析HTML利器AngleSharp介绍
解析HTML利器AngleSharp介绍 AngleSharp是基于.NET(C#)开发的专门为解析xHTML源码的DLL组件. 项目地址:https://github.com/FlorianRapp ...
- 【jQuery】 效果
[jQuery] 效果 资料 http://www.w3school.com.cn/jquery/jquery_ref_effects.asp 1. 显示隐藏 hide(); 隐藏 show(): 显 ...
- iOS URL加解密
URL加解密 背景介绍 iOS 下URL加解密,项目使用AFNetworking 虽然是使用HTTPS,但是从安全方面考虑,在很多情况下还是需要对url的参数进行加密的. 接口如 https://19 ...
- C++学习005-循环
C++在循环方面,感觉个C没有身边么区别 while循环 for循环 do while循环 其实 使用Goto也可以写个循环 编写环境vs2015 1. while循环 int main() { in ...
- NetBeans集成SVN代码管理实例
最近给银行做一个小工具,要求用Java做一个C端带界面的小工具,想来想去用NetBeans最合适,因为Eclipse,MyEclipse,IDEA这些做界面得要额外的UI插件,比较麻烦. 我跟同事两个 ...
- Halcon环境搭建
1.Visual Studio 2017安装教程 2.Qt5.9安装教程 3.VS2017中Qt插件安装教程
- Prim求MST最小生成树
最小生成树即在一个图中用最小权值的边将所有点连接起来.prim算法求MST其实它的主要思路和dijkstra的松弛操作十分相似 prim算法思想:在图中随便找一个点开始这里我们假定起点为“1”,以点1 ...
- z 变换
1. z 变换 单位脉冲响应为 \(h[n]\) 的离散时间线性时不变系统对复指数输入 \(z^n\) 的响应 \(y[n]\) 为 \[ \tag{1} y[n] = H(z) z^{n}\] 式中 ...
- 搭建高可用的Eureka注册中心
搭建高可用的Eureka注册中心 一.搭建高可用的Eureka的作用 当服务器因种种原因导致Eureka注册中心(后面简称Eureka)服务当机(服务器跪了,异常关闭停止服务).这样就会影响到整个业务 ...
- 条件随机场CRF
条件随机场(CRF)是给定一组输入随机变量X的条件下另一组输出随机变量Y的条件概率分布模型,其特点是假设输出随机变量构成马尔科夫随机场.实际上是定义在时序数据上的对数线性模型.条件随机场属于判别模型. ...