日常TC计划正式启动!

Easy(250pts):

题目大意:给你一个集合,里面一堆数,初始数为0,给你一个目标数,你可以选择集合中若干个数进行OR操作来得到目标数。问至少删去多少个数,使得你永远无法达成目标,保证集合最多50个数,每个数<=10^9,且集合中的数两两互不相同。

显然我们要按照每个数的二进制位来考虑,由于所有的数<=10^9,所以最多只有30个二进制位。

如果集合中的一个数,存在某一位使得这个数为1,但是目标数为0,那么这个数一定不能取。

(因为如果取了,那么当前的数这一位就变成了1,然而不存在从1变成0的操作,所以永远无法成为目标数)

对于剩下的数,如果不能达到目标数,那么一定是存在一个二进制位使得目标数为1,其它数都是0。

那么显然只要扫一下就可以了。

时间复杂度O(n*logw),代码如下:

 #include <bits/stdc++.h>
using namespace std;
class ORSolitaire
{
public:
int getMinimum(vector <int> numbers,int t)
{
int ans=;
int n=numbers.size();
bool flag[];
for (int i=;i<n;i++)
{
flag[i]=true;
for (int j=;j<=;j++)
if ((numbers[i]&(<<j))&&((t&(<<j))==)) flag[i]=false;
}
for (int i=;i<=;i++)
{
int cnt=;
for (int j=;j<n;j++)
if ((numbers[j]&(<<i))&&flag[j]) ++cnt;
if (t&(<<i)) ans=min(ans,cnt);
}
return ans;
}
};

Medium(600pts):

题目大意:给你一个n*m的01矩阵,你需要尽可能少地改变矩阵中的数(0变成1,1变成0)使得矩阵中至少有r行是回文串,c列是回文串,输出最少操作次数。其中2<=n,m<=14,数据保证n和m都是偶数。

这应该是这场最烦的题目了吧,如果你会玄学优化,说不定可以搜过去~~~(大雾)

我们枚举2^m种的情况,每一列有回文或者不回文的情况,接下来我们考虑使用dp。

考虑dp的状态,如果只是一列一列的进行状态的转移,那么这样显然是不太好做的,因为你不知道这一行是否回文。

于是我们考虑首尾两行,两行两行进行转移。

我们可以先预处理出cost数组,cost[i][j]表示第i行和第n-1-i行一共有j个串是回文串的最小代价。(所以j=0,1,2)

这里我们显然可以通过枚举出2*2的小矩阵,对于2*2我们只要手判就可以了。

接下来考虑转移dp数组,f[i][j]表示前i行和后i行一共有j个串是回文串的最小代价。

于是我们有f[i][j]=min(f[i][j],f[i-1][j-k]+cost[i][k]),中间一些细节(特别是下标)考虑清楚就好了。

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

 #include <bits/stdc++.h>
#define inf 20000007
using namespace std;
int con[][],a[][];
int n,m;
class PalindromeMatrix
{
int countbit(int s)
{
int st=s,ans=;
while (st>)
{
ans+=(st%==);
st/=;
}
return ans;
}
int deal(int p0,int p1,int q0,int q1)
{
if (p0) p0=;
if (p1) p1=;
if (q0) q0=;
if (q1) q1=;
//p means whether two blocks in the row are the same
//q means whether two blocks in the column are the same
//the aim of the function is just to calculate the possible answer of the blocks of size 2*2
int cnt=;
for (int i=;i<=;i++)
for (int j=;j<=;j++)
cnt+=(con[i][j]==);
if (p0+p1+q0+q1>=) return min(cnt,-cnt);
//all the four blocks must be the same if the sum of p&q are not less than 3
else if(p0+p1+q0+q1==)
{
//there must be exact three blocks that are the same or two blocks in the two rows/columns
//then there will be four conditions
if (p0&&p1) return ((con[][]!=con[][])+(con[][]!=con[][]));
if (q0&&q1) return ((con[][]!=con[][])+(con[][]!=con[][]));
int tot=;
if (p0&&q0) tot=cnt-(con[][]==);
if (p0&&q1) tot=cnt-(con[][]==);
if (p1&&q0) tot=cnt-(con[][]==);
if (p1&&q1) tot=cnt-(con[][]==);
return min(tot,-tot);
} else if (p0+p1+q0+q1==)
{
//there will also be four conditions
int tot=;
if (p0) tot+=(con[][]!=con[][]);
if (p1) tot+=(con[][]!=con[][]);
if (q0) tot+=(con[][]!=con[][]);
if (q1) tot+=(con[][]!=con[][]);
return tot;
}
//then the answer must be 0
else return ;
}
int calc(int rowcnt,int st)
{
int cost[][],f[][];
for (int i=;i<n/;i++)
{
for (int j=;j<=;j++) cost[i][j]=*m;
//x means whether two blocks in the same row are the same
//y means whether two blocks in the same column are the same
for (int x1=;x1<=;x1++)
for (int x2=;x2<=;x2++)
{
int now=;
for (int j=;j<m/;j++)
{
int y1=st&(<<j),y2=st&(<<(m-j-));
con[][]=a[i][j];
con[][]=a[i][m-j-];
con[][]=a[n-i-][j];
con[][]=a[n-i-][m-j-];
now+=deal(x1,x2,y1,y2);
}
cost[i][x1+x2]=min(cost[i][x1+x2],now);
}
}
for (int i=;i<=n/;i++)
for (int j=;j<=rowcnt;j++)
f[i][j]=inf;
f[][]=;
for (int i=;i<=n/;i++)
for (int j=;j<=rowcnt;j++)
for (int k=;k<=&&k<=j;k++)
f[i][j]=min(f[i][j],f[i-][j-k]+cost[n/-i][k]);
return f[n/][rowcnt];
}
public:
int minChange(vector<string> s,int rowcnt,int colcnt)
{
n=s.size(),m=s[].length();
for (int i=;i<n;i++)
for (int j=;j<m;j++)
a[i][j]=s[i][j]-'';
int ans=inf;
for (int st=;st<(<<m);st++)
if (countbit(st)==colcnt) ans=min(ans,calc(rowcnt,st));
return ans;
}
};

Hard(900pts):

题目大意:给你两个整数A,B,求直线y=ax+b将平面分成了多少个部分,(a=0,1...A-1,b=0,1,...B-1)其中1<=A,B<=1200。

这是个很棒棒的公式题。

我们考虑把所有的直线一条一条加进来,那么我们只需要统计出每加进来一条直线会多出多少个平面就可以了。

对于直线y=ax+b,显然它不会和y=ax+c,其中c不等于b的直线相交。

于是我们只需要考虑直线y=ax+b和y=cx+d其中c<a且d<B的直线相交。

我们还需要注意到一个细节就是,如果有三条直线交在了同一个点上,那么对于答案的贡献度会减少1,

换句话说,我们要考虑的本质不是有多少直线相交,而是它们会相交出多少个交点。

考虑直线y=ax+b和y=cx+d,它们的交点P,那么Xp=(d-b)/(a-c),

我们将Xp视为p/q,那么我们只需要考虑本质不同的p/q有多少就可以了,

我们来观察一下p和q的范围,

其中p=d-b,那么p在-b~B-b的范围内,而q=a-c,于是q在1~a的范围内。

那么本质不同的p/q是什么呢,也就是p/q的数值不同,那么只需要考虑p和q互质的情况就可以了。

这里可以用莫比乌斯反演呢,但是A,B<=1200,所以直接暴力就好了。

所以这一题我们先预处理出1~i,1~j中有多少对数互质,接下来直接统计答案就可以了。

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

 #include <bits/stdc++.h>
using namespace std;
long long f[][];
class LotsOfLines
{
int gcd(int a,int b)
{
if (b==) return a;
return (gcd(b,a%b));
}
public:
long long countDivisions(int a,int b)
{
memset(f,,sizeof(f));
for (int i=;i<=a;i++)
for (int j=;j<=b;j++)
f[i][j]=f[i-][j]+f[i][j-]-f[i-][j-]+(gcd(i,j)==);
long long ans=+b;
for (int i=;i<a;i++)
for (int j=;j<b;j++)
ans=ans++f[i][j]+f[i][b-j-];
return ans;
}
};

完结撒花~

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

  1. Topcoder SRM 602 div1题解

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

  2. Topcoder SRM 607 div1题解

    好久没来写了,继续继续... Easy(250pts): //前方请注意,样例中带有zyz,高能预警... 题目大意:给你一个字符串,中间有一些是未知字符,请你求出这个字符串的回文子串个数的期望值.数 ...

  3. topcoder srm 600 div1

    problem1 link 首先,如果一个数字的某一位是1但是$goal$的这一位不是1,那么这个数字是不用管它的.那么对于剩下的数字,只需要统计在$goal$为1的位上,这些数字对应位上也是1的数字 ...

  4. Topcoder SRM 608 div1 题解

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

  5. Topcoder SRM 606 div1题解

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

  6. Topcoder SRM 605 div1 题解

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

  7. Topcoder SRM 604 div1题解

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

  8. Topcoder SRM 603 div1题解

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

  9. Topcoder SRM 601 div1题解

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

随机推荐

  1. tcl之控制流-for

  2. 为什么 redis 单线程却能支撑高并发

    redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发? 这个是问 redis 的时候,最基本的问题吧,redis 最基本的一个内部原理 ...

  3. C指针(1)——指针在数组中的应用(程序讲解)

    2-1.c数组指针的定义: #include <stdio.h> int main() { char str[]="China Beijing Fujian"; //定 ...

  4. jira安装说明

    阅读目录 1.1 jira说明 1.2 安装配置jira 1.3 web界面访问 1.4 创建第一个项目 1.5 参考文献 回到顶部 1.1 jira说明 JIRA是Atlassian公司出品的项目与 ...

  5. Java 的单元测试

    有点需要注意,当 JUnit 主线程退出,子线程也会跟着退出,需要使用子线程的 join() 方法使主线程等待 Maven 依赖 <dependency> <groupId>j ...

  6. samba server on Mac OS X Lion Server

    一般Mac共享通过配置wins,smb即可实现.注意在同一个工作组! 参考:http://computers.tutsplus.com/tutorials/how-to-set-up-an-smb-s ...

  7. linux 多播

    1.概念 单播是用于两个主机之间传送数据,广播是一个主机对局域网内的所有主机发送数据.而多播,又称为组播,它是对一组特定的主机通信.将网络上同一类型 业务逻辑上分组,只和组内的成员通信,其它主机没有加 ...

  8. 《数据结构》C++代码 Splay

    Splay,伸展树.之所以先写这个课内并不怎么常用的数据结构,是因为本人非常喜欢Splay,我觉得这是非常有美感且灵活的一种平衡树.在此先声明,我的伸展树写法来源于CLJ大牛,基础好的同学可以去他的博 ...

  9. HTML5标签学习笔记

    <!DOCTYPE html> <html lang="zh-cn"> <head> <meta http-equiv="con ...

  10. 牛客网暑期ACM多校训练营(第一场):J-Different Integers(分开区间不同数+树状数组)

    链接:J-Different Integers 题意:给出序列a1, a2, ..., an和区间(l1, r1), (l2, r2), ..., (lq, rq),对每个区间求集合{a1, a2, ...