A

  树形dp是看起来比较靠谱的做法 , 但是转移的时候不全面就会出错 , 从贪心的角度出发 , 首先让第一量车走最长路,

  然后就会发现递归结构 , 得到递归式 f[i] = ( f[i-2] + f[i-3] + .. + f[1]) * 2 + 1;

  贪心的正确性 , 可以根据dp方程证出来 , 不过还是蛮显然的...

  

 #define maxn 1000100
#define mod 1000000007
#define INF (1ll<<60)
llong dp[maxn][];
class TrafficCongestion {
public:
int theMinCars(int);
}; llong dfs(int h,int s)
{
int i,j;
llong resa,resb,resc;
dp[][] = ;
dp[][] = ;
dp[][] = ;
for ( i= ; i<=h ; i++ )
for ( j= ; j< ; j++ )
{
resa = resb =resc = INF;
if (j==)
{
resa = dp[i-][] + dp[i-][] + 1ll; resa %= mod;
resb = dp[i-][] + dp[i-][]; resb %= mod;
resc = dp[i-][] + dp[i-][]; resc %= mod;
}
else if (j==)
{
resa = dp[i-][] * 2LL % mod;
resb = dp[i-][] + dp[i-][]; resb %= mod;
}
else if (j==)
{
resa = dp[i-][] + dp[i-][]; resa %= mod;
resb = dp[i-][]*2LL + 1LL; resb %= mod;
}
resa = min(resa,resb);
resa = min(resa,resc);
dp[i][j] = resa;
}
return dp[h][s];
}
int TrafficCongestion::theMinCars(int h)
{
memset(dp,-,sizeof(dp));
llong ans = dfs(h,);
return ans;
}

B

  假设每个value只有一个 , 那么只要构造递增次数为K的序列就行了 ,  构造方法可以是:先取前k个作为k个递增序列的起点 ,

  剩下的就是n-k个元素分配给,k个集合求方案数 , 但是这样无法保证每个序列递增 ,不过还是给我们一个启示:按递增顺序考虑.

  定义dp[i][j] 为 前i个元素 , 已经构造了j个递增序列的方案数.

  dp[i+1][j] = dp[i][j] *  j + dp[i][j-1]

  拓展到每个value可能出现多个的情况时 ,转移要乘上组合数.

 using namespace std;
#define maxn 1300
typedef long long llong;
const llong mod = ;
class LISNumber {
public:
int count(vector <int>, int);
};
llong dp[][maxn],c[maxn][maxn];
int n,sum[maxn];
int LISNumber::count(vector <int> card, int K)
{
int i,j,k;
n = card.size();
for ( i= ; i<n ; i++ ) sum[i] = i? sum[i-]+card[i] : card[i]; for ( i=,c[][]= ; i<maxn ; i++ )
for ( j= ; j<=i ; j++ )
{
c[i][j] = j?c[i-][j-]+c[i-][j] : ;
c[i][j] %= mod;
} memset(dp,,sizeof(dp));
dp[][] = ;
for ( i= ; i<n ; i++ )
for ( j= ; j<=sum[i] && j<=K ; j++ ) if (dp[i][j])
{
// printf("dp[%d][%d]=%lld\n",i,j,dp[i][j]);
for ( k= ; k<=j && k<=card[i] ; k++ )
{
llong pos,add,x;
add = card[i]-k;
pos = ( (i?sum[i-]:) + ) - j + k;
x = c[j][k] * c[pos+add-][pos-] %mod * dp[i][j] % mod;
// printf("add to dp[%d][%d] ,k=%d: %lld\n",i+1,(int)(j+add),k,x);
dp[i+][j+add] += x;
dp[i+][j+add] %= mod;
}
}
// for ( i=0 ; i<=n ; i++ )
// for ( j=0 ; j<=K ; j++ ) if (dp[i][j]) printf("dp[%d][%d]=%lld\n",i,j,dp[i][j]);
return dp[n][K] % mod;
}

C

  (计算几何不会 , 看题解撸了好久..)

  判断点是否在三角形内部或边界:

    顺时针地考虑每条边e , 如果黑点在e下方 , 则在内部 , 否则在外部 , 用叉积判断 , 注意叉积为0的时候 ,是恰好在边界上,应判为在内部;

  统计方案数:

    为了不重复统计 , 3元组(a,b,c)应该为升序 .

    于是有了朴素的办法: 枚举三元组.

    然后考虑: 对于确定的a , b有一个取值范围来保证 e(a,b) 这条边合法 , c也有一个取值范围来保证 e(c,a) 这条边合法 ,

    用f(i)来表示对于点i , 能取的编号最大的点 , 很显然f(i)是递增的 , 然后根据单调性 , 利用"部分和"的技巧 , 可以o(n)统计方案数.

 #define maxn (58585*4+100)
class EnclosingTriangle {
public:
long long getNumber(int, vector <int>, vector <int>);
}; struct node {
llong x,y;
};node e[maxn];
int t,f[maxn]; llong xmult(llong x0,llong y0,llong x1,llong y1) {
return x0*y1 - x1*y0;
} llong sum , add[maxn] , addid[maxn] , front , tail , c; int check(int A,int B,vector<int>x,vector<int> y) {
node a = e[A];
node b = e[B%t];
for (int i= ; i<(int)x.size() ; i++ ) {
if (xmult(a.x-x[i],a.y-y[i],b.x-x[i],b.y-y[i])>) return ;
}
return ;
} void sub(llong d) {
sum -= (tail-front) * d;
// printf("sub: cnt=%lld cut:%lld sum:%lld\n",tail-front,(tail-front)*d,sum);
while (front<tail && add[front]-c<) {
sum -= add[front]-c;
// printf("cut:%lld count:%lld otq:%lld\n",add[front]-c,add[front],addid[front]);
front++;
}
} void ins(int b) {
add[tail] = min(f[b]+,t);
addid[tail] = b;
sum += add[tail++]-c;
} long long EnclosingTriangle::getNumber(int m, vector <int> x, vector <int> y) {
for (int i= ; i< ; i++ ) {
for (int j= ; j<m ; j++ ) {
llong ox[] = {,j,m,m-j};
llong oy[] = {j,m,m-j,};
e[t++] = (node){ox[i],oy[i]};
}
}
for (int i=,j= ; i<t ; i++ ) {
while (check(i,j,x,y)) j++;
j--;
f[i] = j;
// printf ("f[%d]=%d\n",i,j);
}
c = ;
llong res = ;
for (int a=,b= ; a<t ; a++ ) {
llong d = ; while (front<tail && addid[front]<=a) {
sum -= add[front]-c;
// printf("front:%lld tail:%lld cut:%lld sum:%lld\n",front,tail,add[front]-c,sum);
front++;
}
while (f[c]<a+t && c+<t) c++,d++;
if (f[c]<a+t) break;
sub(d);
// printf("before add :sum:%lld c:%lld\n",sum,c);
while (b<=f[a]) {
if (min(f[b]+,t)-c>=) {
ins(b);
if (b==c) res--;
}
b++;
}
res += sum;
// printf("after add: sum:%lld c:%lld b:%d res:%lld\n",sum,c,b,res);
}
return res;
}

  

SRM 585 DIV1的更多相关文章

  1. SRM 585 DIV1 L2

    记录dp(i, j)表示前i种卡片的排列,使得LISNumber为j的方法数. #include <iostream> #include <vector> #include & ...

  2. topcoder srm 585 div1

    problem1 link 最优的策略就是从最低下一层开始,每两层的三个节点的子树都可以用一次遍历覆盖. problem2 link 从大到小依次放置每一种数字,并记录已经放置的数字一共有多少个$m$ ...

  3. Topcoder SRM 643 Div1 250<peter_pan>

    Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...

  4. Topcoder Srm 726 Div1 Hard

    Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...

  5. 图论 SRM 674 Div1 VampireTree 250

    Problem Statement      You are a genealogist specializing in family trees of vampires. Vampire famil ...

  6. SRM 583 DIV1

    A 裸最短路. class TravelOnMars { public: int minTimes(vector <int>, int, int); }; vector<int> ...

  7. SRM 590 DIV1

    转载请注明出处,谢谢viewmode=contents">http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlov ...

  8. Topcoder SRM 602 div1题解

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

  9. 状态压缩DP SRM 667 Div1 OrderOfOperations 250

    Problem Statement      Cat Noku has just finished writing his first computer program. Noku's compute ...

随机推荐

  1. VC++中操作XMLWin32实例

    摘要:VC++中操作XML XML在Win32程序方面应该没有在Web方面应用得多,很多Win32程序也只是用XML来存存配置信息而已,而且没有足够的好处的话还不如用ini.VC++里操作XML有两个 ...

  2. How to Read, Write XLSX File in Java - Apach POI Example---reference

    No matter how Microsoft is doing in comparison with Google, Microsoft Office is still the most used ...

  3. linux 声音大小调整的命令

    alsamixer 输入上面的命令 回车即可看到图形界面,界面如下 ┌──────────────────────────── AlsaMixer v1.0.27.1 ──────────────── ...

  4. SSH端口修改

    打开SSDH配置文件: vim /etc/ssh/sshd_config 添加端口号:Port 60000 重启服务:service sshd restart

  5. Centos6 安装vnc

    Centos6 安装vnc 1. 安装 使用yum方式安装 yum install tigervnc-server tigervnc #启动 vncserver #重启动 /etc/init.d/vn ...

  6. Config配置文件读写

    config文件读写操作(文字说明附加在程序中) App.config文件 <?xml version="1.0" encoding="utf-8" ?& ...

  7. JavaScript基础(一)

    JavaScript一.什么是JavaScript?脚本描述语言,网页交互特效,说白了,就是实现HTML实现不了的效果.(JavaScript是一种基于对象.事件驱动的简单脚本语言,嵌入在HTML文档 ...

  8. DotNet中的计时器线程计时器

    转载自:http://hi.baidu.com/wingingbob/item/9f1c9615f3b24d5f2b3e225c 基于多线程设计,计时器工作在ThreadPool线程上,存在事件的重入 ...

  9. 修复 status 为 unusable 的 index

    以DBA权限登陆,执行以下脚本即可. declare     -- 指向所有 UNUSABLE 状态的 index 的游标      cursor c is        select index_n ...

  10. Swift - 35 - 使用闭包简化语法

    //: Playground - noun: a place where people can play import UIKit // 初始化一个整数数组 var arr = [1, 3, 5, 7 ...