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 题意:有如下图所示的平面,每个六边形有坐标.将其中一些六边形染色,要求有边相邻的两个六边形不能染同一种颜色.给定哪些六边形需要染色,问最少需要多少种颜色. 解法: ...
随机推荐
- Android开发ScrollView上下左右滑动事件冲突整理一(根据事件)
主要通过重写 onInterceptTouchEvent 事件来解决,代码如下: package com.cm.android.pad.view.itemView; import android.co ...
- 转:SVN使用教程总结
转自:http://www.cnblogs.com/tugenhua0707/p/3969558.html SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成很多不同的版 ...
- 构建可比较的对象(IComparable)
IComparable接口 System.IComparable接口指定了一种允许一个对象可基于某些特定键值进行排序的行为. namespace System { [ComVisible(true)] ...
- Java POI 导出excel表
1.首先下载poi-3.6-20091214.jar,下载地址如下: http://download.csdn.net/detail/evangel_z/3895051 2.Student.java ...
- windows 8.1 administrator相关设置
一.windows 8.1 开启administrator用户 windows8.1中文版,由于默认不开启administrator用户,所以需要自己手动开启 启用administrator:在cmd ...
- 关于auto和decltype
auto会忽略顶层const,保留底层const ; const int* const p = &i; auto p2 = p; //p2是const int*,不是const int* co ...
- 跟我学android-常用控件之EditText
EditText 是TextView的直接子类,它与TextView的区别在于,EditText可以接受用户输入. 下面通过一个实例来说明EditText的用法 实例:sina 微博的登录界面(注意, ...
- 优化HTTP前端请求构建高性能ASP.NET站点
HTTP请求的优化 在一个网页的请求过程中,其实整个页面的html结构(就是页面的那些html骨架)请求的时间是很短的,一般是占整个页面的请求时间的10%-20%.在页面加载的其余的时间实际上就是在 ...
- php 用于绘图使用的颜色数组
$colorArr = array(0x912CEE, 0x99ff00, 0x312520, 0x801dae, 0x25f8cb, 0xCC3333, 0x808080, 0xa29b7c, 0x ...
- python学习第十六天 --继承进阶篇
这一章节主要讲解面向对象高级编程->继承进阶篇,包括类多继承介绍和继承经典类和新式类属性的查找顺序不同之处. 多继承 上一章节我们讲到继承,子类继承父类,可以拥有父类的属性和方法,也可以进行扩展 ...