SRM475 - SRM479(1-250pt,500pt)
SRM 475
DIV1 300pt
题意:玩游戏。给一个棋盘,它有1×n(1行n列,每列标号分别为0,1,2..n-1)的格子,每个格子里面可以放一个棋子,并且给定一个只含三个字母WBR,长度为n的字符串,代表每个格子的颜色。在游戏开始时,r个棋子随机摆放在这n个格子里(每个棋子摆在每个格子里的概率相同),问游戏结束时,这些格子里所剩棋子数的期望。游戏的规则为(记这个棋盘的列数为size):
1、如果棋子在0格,则向右移动一格;
2、如果棋子在size-1或size-2格,则向左移动一格;
3、其他棋子若在颜色为W的格子则左移一格,若在颜色为B的格子则右移一格,若在颜色为R的格子:若该旗子目前并未移动过,则左移一格,否则返回上一步所在的格子。
4、所有棋子移动完成后,对与所有格子,如果某个格子含有不止一个棋子,则将该格所有棋子移出棋盘。
5、第4步完成后,棋盘的列数减少1,(即从1*size大小的棋盘变为1*(size-1)),若棋盘列数等于2,则游戏结束,否则循环进行1-5步。
2 <= n <= 17
解法:由于棋盘大小最多也就1*17格,可以直接暴力模拟所有情况,最慢也就O(C(17,8) * 17)的复杂度,能接受。
但是,题解给出了一种很好的方法。
首先,通过观察发现以下几点:1、称“游戏开始时出现在奇数格的棋子“为奇数棋,其他称为偶数棋。经过一次1-3步循环,所有奇数棋变为偶数棋或者被移出棋盘,所有偶数棋变为奇数棋或被移出棋盘。
2、每次将某一格的棋子移出棋盘,移出的数量必定为2,且移出的全为奇数棋或者全为偶数棋。换句话说,如果游戏开始时,奇数棋的数量为奇数(偶数),游戏结束时,奇数棋数量也为奇数(偶数)。偶数棋也如此。
3、游戏结束时,棋盘大小一定为1*2,并且每格含有0个或1个棋子。也就是说,游戏结束时剩下0个或1个奇数棋,0个或1个偶数棋。
由1,2,3可以得出结论,若游戏开始时有x个奇数棋,有y个偶数棋,则游戏结束时有(x%2 + y%2)个棋子。然后,遍历所有游戏开始时可能出现的棋子摆放情况即可。
tag:think, good
/*
* Author: plum rain
* score : 0
* study form: www.topcoder.com
*/
#line 11 "RabbitStepping.cpp"
#include <sstream>
#include <stdexcept>
#include <functional>
#include <iomanip>
#include <numeric>
#include <fstream>
#include <cctype>
#include <iostream>
#include <cstdio>
#include <vector> using namespace std; #define SZ(v) ((int)(v).size()) class RabbitStepping
{
public:
double getExpected(string field, int r){
int n = SZ (field);
int num = , sum = ;
for (int i = ; i < (<<n); ++ i){
if (__builtin_popcount(i) != r) continue; int e = , o = ;
for (int j = ; j < n; ++ j)
if (i & (<<j)){
e += j & ;
o += - (j&);
}
num += (e%) + (o%);
++ sum;
}
return (num + 0.0) / sum;
}
};
DIV1 600pt
题意:第一年7月天上掉下一对小兔子。之后每年3月,老兔子生一对小兔子,原来的小兔子升级为老兔子;某些年的11月,消失一半兔子,消失的兔子总是年龄较大的那些。现在给定最多50个兔子会消失一半的年份,问第K(K<=1e7)年的12月一共有多少兔子。答案模MOD=1,000,000,009。
解法:不会- -
tag:math, good
SRM 476
DIV1 250pt
题意:有n只羊,给定两个数组{an}和{bn},ai表示第i只羊的食量,bi表示第i只羊的附加食量,并且给定拥有的食物总量为tot。如果主人饲养了m只羊,则对于一只羊k,它消耗的食物总量为a[k] + m*b[k]。要求所有羊消耗的食物总量之和不超过tot的情况下,求饲养的羊的数量最多为多少只。
(1<= n <= 50)
解法:主人养k只羊时花费食物总量最少为t,则可以t可以在O(nlogn)(使用一次快排即可)。然后从k = n to 1找最多可能饲养的羊的数量。
tag:greedy
/*
* Author: plum rain
* score : 204.20
*/
#line 11 "Badgers.cpp"
#include <sstream>
#include <stdexcept>
#include <functional>
#include <iomanip>
#include <numeric>
#include <fstream>
#include <cctype>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm> using namespace std; #define PB push_back
#define SZ(v) ((int)(v).size())
#define out(x) cout<<#x<<":"<<(x)<<endl
#define tst(a) cout<<#a<<endl typedef vector<int> VI; class Badgers
{
public:
int feedMost(vector <int> hun, vector <int> g, int tot){
int size = SZ (hun);
VI tmp;
for (int n = size; n > ; -- n){
tmp.clear();
for (int i = ; i < size; ++ i)
tmp.PB (hun[i] + g[i]*(n-));
sort (tmp.begin(), tmp.end()); int num = ;
for (int i = ; i < n; ++ i)
num += tmp[i];
if (num <= tot) return n;
}
return ;
}
};
DIV1 550pt
题意: 小明有一些朋友(n个),小明的朋友还有一些朋友,他们可能是小明的朋友也可能不是。一共有m个人,他们的房子标号为1-m。小明要从自己家(1号房子)出发,然后去拜访自己的朋友。每次,小明所在的房子的主人都会对房子主人自己的朋友进行一次随机排列,小明只能从前k个人中选择一个人拜访,或者不再拜访任何人。注意,选择的这个人必须是小明没有拜访过的,并且他是小明的朋友。问,在小明采取最优策略下,他能拜访完所有朋友的概率最大是多少。
每个人最多15个朋友,一共最多36个人,K >= 1。
解法:首先,要用状态压缩,用opt表示小明的所有朋友(最多15个)是否被拜访过,1为未拜访。数组dp[i][j]表示拜访状态为i,现在在房子j的状态下能拜访完所有朋友的概率。
dp[i][j] = sum{(给出随机排列后,小明会选择t作为下一个拜访地点的可能性) * dp[i^(1<<t)][t]}(t为所有小明的朋友, 且i & (1<<t)为真)。
上面状态转移方程只剩下一个问题没有解决,就是“给出随机排列后,小明会选择t作为下一个拜访地点的可能性”,而这个可以通过讨论dp[i^(1<<t)][t]的大小易求,具体见代码。
tag:状压dp, good
/*
* Author: plum rain
* score : 0
*/
#line 11 "FriendTour.cpp"
#include <sstream>
#include <stdexcept>
#include <functional>
#include <iomanip>
#include <numeric>
#include <fstream>
#include <cctype>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <utility> using namespace std; #define CLR(x) memset(x, 0, sizeof(x))
#define PB push_back
#define SZ(v) ((int)(v).size())
#define out(x) cout<<#x<<":"<<(x)<<endl
#define tst(a) cout<<#a<<endl typedef vector<int> VI; int C[][], num[];
double dp[<<][];
bool pat[][];
VI m;
int n, k; void C_table(int maxx)
{
CLR (C);
C[][] = ;
for (int i = ; i <= maxx; ++ i){
C[i][] = C[i][i] = ;
for (int j = ; j < i; ++ j)
C[i][j] = C[i-][j] + C[i-][j-];
}
} bool cmp(pair<double, int> a, pair<double, int> b)
{
return a.first > b.first;
} double choose(int num, int pos)
{
if (num < k)
return (double)(pos == );
if (num - pos < k) return 0.0;
return (double)C[num-pos-][k-] / C[num][k];
} double gao (int opt, int pos)
{
vector<pair<double, int> > cur; cur.clear();
for (int i = ; i < n; ++ i)
if (opt&(<<i) && (pos == - || pat[m[pos]][m[i]]))
cur.PB(make_pair(dp[opt^(<<i)][i], i)); sort (cur.begin(), cur.end(), cmp);
double ret = 0.0;
for (int i = ; i < SZ (cur); ++ i)
ret += choose(pos==-?n:num[m[pos]], i) * dp[opt^(<<cur[i].second)][cur[i].second];
return ret;
} class FriendTour
{
public:
double tourProbability(vector <string> fri, int K){
C_table(); CLR (pat); CLR (num); m.clear();
int tmp = ;
for (int i = ; i < SZ (fri); ++ i){
string s = fri[i]; tmp = ;
for (int j = ; j < SZ (s); ++ j){
if (j == SZ(s)- || s[j] == ' '){
if (j == SZ(s)-)
tmp = tmp * + s[j] -'';
-- tmp;
if (!i) m.PB (tmp);
pat[i][tmp] = ;
++ num[i];
tmp = ;
continue;
}
tmp = tmp * + s[j] - '';
}
}
n = SZ (m); k = K; CLR (dp);
for (int i = ; i < n; ++ i) dp[][i] = 1.0;
for (int i = ; i < (<<n); ++ i)
for (int j = ; j < n; ++ j)
dp[i][j] = gao (i, j);
return gao((<<n)-, -);
}
};
SRM 477
DIV1 250pt
题意:摆放六边形形成如下图案,然后将所有六边形涂成红蓝两色,求两种颜色的的六边形的公共边的总长度。

解法:直接分类讨论就好。题解的代码比我的代码简洁多了- -
tag:water
/*
* Author: plum rain
* score : 176.61
*/
#line 11 "Islands.cpp"
#include <sstream>
#include <stdexcept>
#include <functional>
#include <iomanip>
#include <numeric>
#include <fstream>
#include <cctype>
#include <iostream>
#include <cstdio>
#include <vector> using namespace std; #define SZ(v) ((int)(v).size())
#define out(x) cout<<#x<<":"<<(x)<<endl
#define tst(a) cout<<#a<<endl typedef vector<string> VS;
VS k; int count (int x, int y)
{
int ret = ;
if (k[x][y+] == '.') ++ ret;
if (k[x][y-] == '.') ++ ret; if (x & ){
if (x > ){
if (k[x-][y] == '.') ++ ret;
if (y+ < SZ(k[x-]) && k[x-][y+] == '.') ++ ret;
}
if (x < SZ(k)-){
if (k[x+][y] == '.') ++ ret;
if (y+ < SZ(k[x+]) && k[x+][y+] == '.') ++ ret;
}
return ret;
} if (x > && k[x-][y] == '.') ++ ret;
if (x > && y > && k[x-][y-] == '.') ++ ret;
if (x+ < SZ(k) && k[x+][y] == '.') ++ ret;
if (x+ < SZ(k) && y > && k[x+][y-] == '.') ++ ret;
return ret;
} class Islands
{
public:
int beachLength(vector <string> kin){
k.clear();
k = kin;
int n = SZ (k);
int ans = ;
for (int i = ; i < n; ++ i){
string s = k[i];
int len = SZ (s);
for (int j = ; j < len; ++ j)
if (s[j] == '#') ans += count (i, j);
}
return ans;
}
};
DIV1 500pt
题意:如果数组(a, b)满足以下条件:1、存在a*a + b*b = c*c且a,b,c均为整数;2、a,b互素。则称a,b为好数组。给定n个数(可能重复),求从中最多可以拿出多少对好数组。
解法:有两种方法,可以将每个数拆成两个点然后求一个二分图最大匹配,ans = 匹配数/2;另一种方法,由题目条件容易推得,a,b必为一奇一偶。所以做一个奇偶二分图匹配即可。可是我不会二分图匹配- -,所以不会做.....
tag:二分图最大匹配
SRM 479
DIV1 250pt
题意:有一排座位1-n,每个座位上的客人需要咖啡或者茶,服务员每次在第0号位置将水壶添满茶或者咖啡,需要47秒。服务员的水壶装满一次只能给7个需求相同(茶或者咖啡)人倒,服务员从每个座位k走到k-1或者k+1需要1秒,给每个人倒水需要4秒。给出每个客人的需求,问服务员满足所有客人的需求所需要的最短时间。
解法:贪心即可。之前自己写的代码好搓,还错了- -,然后看了summary里面别人的代码,自己又写了一份。
tag:greedy
SRM475 - SRM479(1-250pt,500pt)的更多相关文章
- SRM 358(1-250,500pt)
DIV1 250pt 题意:电视目前停留在第100台,有一个遥控器,可以向上或向下换台(需要按键一次),也可以按一些数字,然后直接跳到该台(需要按键次数等于数字数,不需要按确定键).但是,这个遥控一些 ...
- SRM 601(1-250pt,500pt)
DIV1 250pt 题意:有很多袋子,里面装有苹果和橘子(也可能没有),给出每个袋子里有多少个苹果,多少个橘子.如果每个袋子里含有水果的总数都不小于x个,则可以从每个袋子里都拿出x个水果(拿出苹果和 ...
- SRM468 - SRM469(1-250pt, 500pt)
SRM 468 DIV1 250pt 题意:给出字典,按照一定要求进行查找. 解法:模拟题,暴力即可. tag:water score: 0.... 这是第一次AC的代码: /* * Author: ...
- SRM470 - SRM474(1-250pt,500pt)(471-500pt为最短路,474-500pt未做)
SRM 470 DIV1 250pt 题意:有n个房间排成一排,相邻两个房间之间有一扇关闭着的门(共n-1扇),每个门上都标有‘A’-‘P’的大写字母.给定一个数n,表示第n个房间.有两个人John和 ...
- SRM479
250pt: 题意:有一排一共44,777,777个人,每个人需要咖啡或者茶,队伍的头部有一台饮料机,有一个空姐负责给所有人送饮料,她一开始在也头部.空姐拿一个水壶,一开始是空的,可以在饮料机的地方加 ...
- SRM475
250pt: 题意:有最长N=17的一条格子,每个格子是W.B和R三种颜色之一,当某个格子上有兔子时,下一个回合该兔子按照以下的规则移动: 如果兔子在第一个格子,则向右移动一格: 否则如果兔子在倒数两 ...
- SRM DIV1 500pt DP
SRM 501 DIV1 500pt SRM 502 DIV1 500pt SRM 508 DIV1 500pt SRM 509 DIV1 500pt SRM 511 DIV1 500pt SRM 5 ...
- SRM 600(1-250pt,500pt)
DIV1 250pt 题意:给定一个vector<int>A,若能从里面选出一些数,使得他们按位或的值为x,则称x为吉利数.给定k,问最少要从A里面去掉多少个数,才能使k变为不吉利数. 解 ...
- SRM593(1-250pt,500pt)
SRM 593 DIV1 250pt 题意:有如下图所示的平面,每个六边形有坐标.将其中一些六边形染色,要求有边相邻的两个六边形不能染同一种颜色.给定哪些六边形需要染色,问最少需要多少种颜色. 解法: ...
随机推荐
- Windows与Linux文件共享
Windows与Linux文件共享 Samba服务器 安装Samba服务器 rpm –ivh /mnt/Packages/Samba-3.5.10-125.el6.i686.rpm 添加用户并修改密码 ...
- HTML5中的二进制大对象Blob(转)
HTML5中的Blob对象和MYSQL中的BLOB类型在概念上是有点区别的.MYSQL中的BLOB类型就只是个二进制数据容器.而HTML5中的Blob对象除了存放二进制数据外还可以设置这个数据的MIN ...
- updatepanel的用法之triggers
triggers有的两种触发器asyncpostbacktrigger和postbacktrigger.asyncpostbacktrigger(异步回调触发器):局部刷新,只刷新updatepane ...
- iOS开发中的常用宏定义
在iOS开发的过程中合理的使用宏定义能够极大提高编码的速度,下面是一些常用的宏定义,部分内容来自互联网 Log // 调试状态, 打开LOG功能 #ifdef DEBUG #define GLLog( ...
- Java study 1:The note of studying Socket which based UDP
UDP concept: UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参 ...
- JavaScript--模拟网络爬虫
<!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...
- ubuntu用户及用户组文件信息
1.用户帐号文件 /etc/passwd中存放当前系统的用户列表及用户基本的设置信息: 文件中每一行对应一个用户信息,用户信息用":"来分隔,各项内容含义如下: 用户名:用户密码: ...
- c语言中3n+1溢出问题解决
3n+1问题是一个简单有趣而又没有解决的数学问题.这个问题是由L. Collatz在1937年提出的.克拉兹问题(Collatz problem)也被叫做hailstone问题.3n+1问题.Hass ...
- Java学习----Java程序结构
1.什么是类 在源文件中程序员自己定义的通过class关键字,自己给类名这样的定义的一个类,而类里包含一个或多个方法 2.什么是源文件 由程序员使用java语言编写的以.java为结尾的一个文件 3. ...
- css 雪碧图 及jquery定位代码
无意间发现了一个很神奇的事情,就是 鼠标悬停在图片上方会切换,起初以为图标是单独插入的.但发现居然是一张完整的图片. 一万只草泥马在心中奔腾.这是怎么实现的? 后来询问得知,这是css精灵技术(spr ...