2016百度之星总结帖

2016百度之星总结帖

测试赛

选的2015资格赛的部分题目,第二题字符串处理,第三题map计数

1001 大搬家

f f (x) = x

两次置换后回到原位

dp a->b && b->a,考虑n个数

如果它独自成对,那么就有s[n-1];

如果它与前面某个成对,首先可以有n-1个可取,然后每个都有s[n-2];

故s[n] = s[n-1] + (n-1)s[n-2];

1004 放盘子

今天他向来访者们提出一个恶俗的游戏。他和来访者们轮流往一个正多边形内放盘子。最后放盘子的是获胜者,会赢得失败者的一个吻。玩了两次以后,小度熊发现来访者们都知道游戏的必胜策略。现在小度熊永远是先手,他想知道他是否能获胜。

脑洞题,看能不能再中间放一个盘子

资格赛

1001求字符串一段的hash

S[a,b] = S[b] - S[a-1]

但是这里是除法= =所以涉及乘法逆元

费马小定理:

p is prime => x^(p-1) = 1(mod p)

LL mod_pow(LL x, LL n) {
LL res = 1;
while(n) {
if(n & 1) res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res%mod;
}

据说可以用线段树做..

1002全1序列

度熊面前有一个全是由1构成的字符串,被称为全1序列。你可以合并任意相邻的两个1,从而形成一个新的序列。对于给定的一个全1序列,请计算根据以上方法,可以构成多少种不同的序列

高精度fib

1004统计一种无序集合出现次数

sort后丢到map统计

1003 字典树

增加功能: 前缀删除和存在该前缀即可

这道题让我发现以前理解的字典树是错误的..

字典树其实是一个节点数组 tr[节点数][26],而不是指针无限扩展= =

插入单词时,到达一个节点,该节点的次数+1;删除单词时,先判断删除的这个前缀在当前字典树里是否存在,如果存在的话,得到这个单词结尾节点的次数m,然后用删除函数将路径上的每个节点都减去m。

所以解决方案是,当插入单词是,判断当前节点的次数是不是1,如果是1的话说明之前这个位置是断开的,就将当前节点之后所连接的节点次数清空。

1005 闭包

小度熊是一个尽职尽责的程序熊,每天产出数千行的代码,代码当中存在很多判断条件。度熊想让自己代码中的这些条件不存在交集。为了简化问题,一个条件可以是一个『简单条件』或者是一个『复合条件』,简单条件由『变量』、『比较符』和『运算数』组成,其中『变量』是用小写字符表示的一串字符,『运算数』仅为整数,『运算符』包括:<、>、<=、>=、==。分别代表:小于、大于、小于等于、大于等于和等于关系。简单条件的格式固定,左边为变量名,中间为操作符,右边为数字。若干个『简单条件』中间通过英文逗号组成一个『复合条件』,各『简单条件』之间是逻辑与的关系,例如:

简单条件: a > 100

复合条件: duxiong < 1000 , a > 100

初次读题目特别像子臻老师编的那本题解里面的floyd判断闭包

但是这个题目是判断多个,而且有常数

这道题的思路是判断每个变量名的合法取值范围是否为空集

所以…就是一道模拟题?!!!…

2016”百度之星” - 初赛(Astar Round2A)

1001 AII X

F(x,m) 代表一个全是由数字xx组成的mm位数字。请计算,以下式子是否成立:F(x,m) mod k ≡ c

1≤x≤9

m\<= 10^{10}

0≤c

/*
双重快速幂,quickPow是x^m
calc中便是对于十进制(位数)的快速幂
偶数: F(x,m/2) * (10^(m/2)+1) 
奇数: F(x,m-1) * 10 + x
*/
inline int quickPow(LL times){
    int ret = 1, base = 10 % p;//base % p
    while(times){
        if(times & 1LL) ret = ret * base % p;
        base = base * base % p;
        times >>= 1;
    } return ret;
};

int calc(LL x){
    if(x == 1LL) return v;
    int ret = calc(x >> 1LL);
    ret = (ret * quickPow(x >> 1) + ret) % k;
    return (x & 1LL) ? ((ret * 10 + v) % k) : ret;
};
  • 快速幂

    f[0]=1f[i]=(f[i-1]*10+x)%k加速递推式

1006 Gym Class

假设最开始每个人有一个唯一的ID,从1到N,在排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作为自己评价这堂课的分数。

有一些同学不希望某个(些)同学排在他(她)前面

所有同学的评价分数最大和

N M <= 100000(N不能再M后面)

一直TLE在优先队列的复杂设置,很简单的思路不能清晰下来当然跪倒底.

贪心,读入N,M的时候记录N的边数和M的度数这时候不需要优先队列参与

但是这里用queue存N的边会爆内存,需要用vector

然后优先队列直接用int,把能放的放进去,每次拿堆顶元素来更新d[边]

1002 Sitting in Line

给一组数据排序,使得相邻数乘积和最大

有一些数字固定.

N <= 16

第一次提交是DFS..写了好久真是手生,理所当然T

看到N<=16就觉得是状压DP..然而没写过QAQ

  • 状态dp [i][j] ,

i为这会哪些数字已经被选(二进制表示)

​ 用__builtin_popcount(i)得到有多少个i

j为最后一个选的数字是哪一个

dp [ i | (1<

//第一个过的人的核心代码
for(int mask=0;mask<(1<1;mask++)
    for(int i=0;iif(ok[mask][i])
        {
            int t=num[mask];
            if(at[t] != -1)
            {
              int j=at[t];
              if(mask&(1<continue;
              dp[mask+(1<max(dp[mask+(1<1<true;
             }
             for(int j=0;jif(mask&(1<continue;
                dp[mask+(1<max(dp[mask+(1<1<true;
             }
          }

1005 BD String

众所周知,度度熊喜欢的字符只有两个:B和D。

今天,它发明了一种用B和D组成字符串的规则:

S(1)=BS(1)=B

S(2)=BBDS(2)=BBD

S(3)=BBDBBDDS(3)=BBDBBDD

S(n)=S(n-1)+B+reverse(flip(S(n-1))S(n)=S(n−1)+B+reverse(flip(S(n−1))

其中,reverse(s)reverse(s)指将字符串翻转,比如reverse(BBD)=DBBreverse(BBD)=DBB,flip(s)flip(s)指将字符串中的BB替换为DD,DD替换为BB,比如flip(BBD)=DDBflip(BBD)=DDB。

虽然度度熊平常只用它的电脑玩连连看,这丝毫不妨碍这台机器无与伦比的运算速度,目前它已经算出了S(2^{1000})S(21000)的内容,但度度熊毕竟只是只熊,一次读不完这么长的字符串。它现在想知道,这个字符串的第LL位(从1开始)到第RR位,含有的BB的个数是多少?

(1≤L≤R≤10^18)

找规律发现 S(n) = 2^n-1…

但是一方面不用高精度S(n)求不出来,另一方面需要直接构造剩下的区间

所以需要分开讨论,

  • 在这个题解中,分类讨论:

    • 如果L,R都在mid右边,那么可以把区间映射到mid左边,此时求B数量,相当于求D数量,因为flip操作。

    • 如果L<=mid && R >= mid,那么可以从mid左右两边取相等长度的区间,剩下的区间在考虑是在mid的左边还是右边,如果是右边的话,就要进行映射,换为求D的数量。

    所以整个算法只需要递归最多60层就可以得出解了。时间复杂度为log(R-L+1)感觉是带标志变换的二分

  • 这个题解的思路是求出

    • T(R)的公式
    • 刚好 : f(k)
    • 多出来的一节 : 前面那节的D的个数(前面那节可以递归~)
    • T(R)-T(L-1)

另外,1003是dfs+线段树,1004是区间DP

初赛RoundB

安利这个题解

1003 瞬间移动

只能往 右且下 移动,求(1,1)到(n,m)的选择,mod 1000000007

2≤n,m≤100000

/*
 1    1    1    1    1    1       1       1       1
 1    2    3    4    5    6       7       8       9
 1    3    6    10    15    21      28      36      45
 1    4    10    20    35    56      84      120     165
 1    5    15    35    70    126     210     330     495
 1    6    21    56    126    252     462     792     1287
 1    7    28    84    210    462     924     1716    3003
 1    8    36    120    330    792     1716    3432    6435
 1    9    45    165    495    1287    3003    6435    12870
 */

打表,一眼看去是a[x][y] = a[x-1][y] + a[x][y-1]

继续找规律,发现a[x][y] = c(x + y - 4, max(x, y) - 2 );

然后用组合数公式算,算除法时候忘记除逆元就模了…Wa一次

居然以为是高精度,折腾了好久反应过来是逆元….就这样吧…858名憾别今年百度之星

高精度一直不取模算法上也可以,但是目测会超时…

1006 中位数计数

给出一组数(n < 8000)求每个数是多少个区间的中位数

  • 分析(暴力T):
    1. O(n)对每个数扫一遍数组,知道到第n位有多少个比它大多少个比它小
    2. O(n2)枚举区间, 通过上面数组求出比他大小的数各多少

​ 当满足big <= (len-1)/2&& sml <= (len-1)/2计数器+1

  • 看别人O(n2)的算法

    • 往左扫时候记录[l,i]l是第x小的数,cnt[i+x]++(统计一共有几个)

    • 往右扫的时候y += cnt[i+x];也就是加上对应位置.

    • int x=0;    cnt[n]++;            
      for (int j=1;i-j>0;j++)           
      {
      if (a[i-j]            
      x=0;
      int y=cnt[n];    
      for (int j=1;i+j<=n;j++)            
      {
      if (a[i+j]

    也就是说左右相比就可以了= =抓住主要矛盾.

1005区间交

nn个非负整数的数列与mm个区间。每个区间可以表示为l_{i},r_{i}l​i​​,r​i​​。

它想选择其中kk个区间, 使得这些区间的交的那些位置所对应的数的和最大。

写了一个dfs..果断T

//优先队列,懒得写函数的FB少年读入变化
//sort后按照first先后排序
for (int i = 1; i <= m; i++) //到底i个区间
{      
  if (q.size() < k)//如果不够k个
  {
    q.push(-a[i].second);//把结尾丢进去(由于是负数在后面)
  }
  else if (-q.top() < a[i].second)//(k个)如果原来最先结尾先于现在结尾,更换
  {    
    q.pop();
    q.push(-a[i].second);        
  }
  if (q.size() == k) 
  {  
    ans = max(ans, s[-q.top()] - s[a[i].first - 1]);//到现在这一个区间的开头        
  }    
}

1001区间的价值

我们定义“区间的价值”为一段区间的最大值*最小值。

一个区间左端点在L,右端点在R,那么该区间的长度为(R-L+1)

现在聪明的杰西想要知道,对于长度为k的区间,最大价值的区间价值是多少。

当然,由于这个问题过于简单。

我们肯定得加强一下。

我们想要知道的是,对于长度为1∼n的区间,最大价值的区间价值分别是多少。

第一行一个数n(1≤n≤100000)。

第二行n个正整数(1≤ai≤109),下标从1开始。

输出n行,每行一个最大乘积

第一直觉是线段树…

  • rmq

  • 左右贪心扫

for (i=1;i<=n;i++)        
{                
  l = r = i;   
  minn=a[i];          
  ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);//初始化,假设a[i]最大值

  while(a[l-1]<=a[i]||a[r+1]<=a[i])
  {           
    while(l>1) 
      if (a[l-1]<=a[i]&&a[l-1]>=minn)//左边的可以更新最小值       
        l--,ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);    
      else break;

    while(rif (a[r+1]<=a[i]&&a[r+1]>=minn)      
        r++,ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]); //右边的可以更新最小值                
      else break;

    if (a[l-1]<=a[i] && a[r+1]<=a[i])  //更新          
    {    
      if (a[l-1]>a[r+1])                 
        l--,minn=a[l],ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);             
      else                 
        r++,minn=a[r],ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);            
    }

    else if (a[l-1]<=a[i]) 
        l--,minn=a[l],ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);   
    else if (a[r+1]<=a[i]) 
        r++,minn=a[r],ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);
  }//end of while        
}//end of for

1004货物运输

公元2222年,l国发生了一场战争。

小Y负责领导工人运输物资。

其中有m种物资的运输方案,每种运输方案形如l_{i},r_{i}。表示存在一种货物从l_{i}运到r_{i}。

这里有n个城市,第i个城市与第i+1个城市相连(这里1号城市和n号城市并不相连),并且从i号城市走到i+1号或者从i+1号走到ii号需要耗费1点时间。

由于高科技的存在,小Y想到了一种节省时间的好方案。在X号城市与Y号城市之间设立传送站,只要这么做,在X号城市走到Y号城市不需要耗费时间,同样的,从Y号城市走到X号城市也不需要耗费时间。

但是为了防止混乱,只能设立这么一条传送站。

现在这些运输方案同时进行,小Y想让最后到达目的地的运输方案时间最短。

第一行两个整数n,m(1≤n,m≤1000000)。

接下来mm行,每行两个整数l_{i},r_{i}(1≤li,ri≤n)

t[a][a] = 0

这么明显的二分= =居然二逼了

诶看代码到一半发现就是求树的直径啊?题解

int solve(int tmp) {
     int right = Inf;
     int up = Inf;
     int down = -Inf;
     int left = -Inf;
     for (int i = 0; i < move.size(); ++i)
        if (move[i].r - move[i].l > tmp) {
            downdate(right, move[i].l + move[i].r + tmp);
            downdate(up, move[i].l - move[i].r + tmp);
            update(down, move[i].l - move[i].r - tmp);
            update(left, move[i].l + move[i].r - tmp);
            if (left > right || down > up) return 0;
        }
     return 1;
}

1002刷题计划

看上去就是一个背包啊..但是过的人实在太少了…

然后发现,是和(A)*和(B),不是和(A*B)

摆在你面前的是n道题目,第 i(1≤i≤n) 道题目能提升ai 点智力值,代码量为 bi KB,无聊值为 ci ,求至少提升m点智力值的情况下,所做题目代码量之和*无聊值之和最小为多少。

然后过了的代码都是Point(x,y)搜索的..

找了一个宏定义少的代码贴过来

#include
#include 
#include 
#include 
#include  
#include   
#include   
#include   
#include   
#include    
#include      
#include      
using namespace std;

typedef long long LL;

const int N=805;

struct Point
{
    int x,y;
};

int n,m,s,a[N],b[N],c[N];
LL Ans,val[N],v[N];
Point f[N];

Point get(LL x,LL y)
{
    for(int i=1;i<=s;i++)
        f[i].x=f[i].y=1e7,val[i]=(LL)1e7*(x+y);
    for(int j=1;j<=n;j++)
        v[j]=b[j]*x+y*c[j];
    for(int j=1;j<=n;j++)
        for(int k=min(m+a[j],s);k>=a[j];k--)
            if(val[k-a[j]]+v[j]for(int i=m+1;i<=s;i++)
        if(f[i].x*x+f[i].y*yreturn c;
}

void dfs(Point a,Point b)
{
    Point c=get(a.y-b.y,b.x-a.x);
    if((c.x-a.x)*(LL)(b.y-a.y)-(c.y-a.y)*(LL)(b.x-a.x)>0)
        dfs(a,c),dfs(c,b);
}

int main()
{
    while(cin>>n>>m)
    {
        s=0;
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&a[i],&b[i],&c[i]),s+=a[i];
        Ans=1LL<<60;
        Point x=get(1,0),y=get(0,1);
        dfs(x,y);
        printf("%I64d\n",Ans);
    }
    return 0;
}
Close

总结

  1. 学好贪心.
  2. 打开脑洞(找规律)
  3. 数论除法乘逆元
  4. 之后才能聊一聊DP(就像省赛一样…挑战级别还没到DP)

头文件系列

百度之星最好的在于可以看到大神们的头文件长什么样…

  • include

    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    using namespace std;
  • stdio读写

    
    #if ( ( _WIN32 || __WIN32__ ) && __cplusplus < 201103L)
    
      #define lld "%I64d"
    
    #else
    
      #define lld "%lld"
    
    #endif
    
    inline void gn(long long&x){
      int sg=1;char c;while(((c=getchar())<'0'||c>'9')&&c!='-');c=='-'?(sg=-1,x=0):(x=c-'0');
      while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';x*=sg;
    }
    inline void gn(int&x){long long t;gn(t);x=t;}
    inline void gn(unsigned long long&x){long long t;gn(t);x=t;}
    inline void gn(double&x){double t;scanf("%lf",&t);x=t;}
    inline void gn(long double&x){double t;scanf("%lf",&t);x=t;}
    inline void gs(char *s){scanf("%s",s);}
    inline void gc(char &c){while((c=getchar())>126 || c<33);}
    inline void pc(char c){putchar(c);}
  • 二进制处理

    
    #define cnti(x) (__builtin_popcount(x))//1的个数
    
    
    #define cntl(x) (__builtin_popcountll(x))
    
    
    #define clzi(x) (__builtin_clz(x))//左起第一个1前0的个数
    
    
    #define clzl(x) (__builtin_clzll(x))
    
    
    #define ctzi(x) (__builtin_ctz(x))//右起第一个1之后0的个数
    
    
    #define ctzl(x) (__builtin_ctzll(x))
    
  • 常数

    typedef long long ll;
    typedef double db;
    typedef pair<int,int> pii;
    typedef vector<int> vi;
    typedef vector vpii;
    
    const int inf=0x3f3f3f3f;
    const db pi=3.14159265358979323846264338327950288L;
    const db eps=1e-6;
    const int mo=0;
    //另一个
    const int low(int x) { return x&-x; }
    const int INF = 0x7FFFFFFF;
    const int mod = 1e9 + 7;
    const int maxn = 1e5 + 10;
  • 函数

    inline ll sqr(ll a){return a*a;}
    inline db sqrf(db a){return a*a;}
    
    
    #define fil(a,b) memset((a),(b),sizeof(a))
    
    
    #define cl(a) fil(a,0)
    
    
    #define siz(x) ((int)(x).size())
    
    
    #define all(x) (x).begin(),(x).end()
    
    
    #define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
    
    
    
    #define rep(i,a,b) for (int i=(a),_ed=(b);i<_ed;i++)
    
    
    #define per(i,a,b) for (int i=(b)-1,_ed=(a);i>=_ed;i--)
    
    
    
    #define pw(x) ((ll(1))<<(x))
    
    
    #define upmo(a,b) (((a)=((a)+(b))%mo)<0?(a)+=mo:(a))
    
    
    #define mmo(a,b) (((a)=1ll*(a)*(b)%mo)<0?(a)+=mo:(a))
    
    
    void getre(){int x=0;printf("%d\n",1/x);}
    void gettle(){int res=1;while(1)res<<=1;printf("%d\n",res);}
    
    template<typename T,typename S>inline bool upmin(T&a,const S&b){return a>b?a=b,1:0;}
    template<typename T,typename S>inline bool upmax(T&a,const S&b){return a1:0;}
    template<typename N,typename PN>inline N flo(N a,PN b){return a>=0?a/b:-((-a-1)/b)-1;}
    template<typename N,typename PN>inline N cei(N a,PN b){return a>0?(a-1)/b+1:-(-a/b);}
    template<typename N>N gcd(N a,N b){return b?gcd(b,a%b):a;}
    template<typename N>inline int sgn(N a){return a>0?1:(a<0?-1:0);}//返回参数的正负
    int qp(int a,ll b){int n=1;do{if(b&1)n=1ll*n*a%mo;a=1ll*a*a%mo;}while(b>>=1);return n;}
    
  • 完整版

    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    
    #include
    
    using namespace std;
    
    #define y0 y0z
    
    
    #define y1 y1z
    
    
    #define yn ynz
    
    
    #define j0 j0z
    
    
    #define j1 j1z
    
    
    #define jn jnz
    
    
    #define tm tmz
    
    
    #define buli(x) (__builtin_popcountll(x))
    
    
    #define bur0(x) (__builtin_ctzll(x))
    
    
    #define bul2(x) (63-__builtin_clzll(x))
    
    
    #define mp make_pair
    
    
    #define pb push_back
    
    
    #define fi first
    
    
    #define se second
    
    
    #define fil(a,b) memset((a),(b),sizeof(a))
    
    
    #define cl(a) fil(a,0)
    
    
    #define siz(x) ((int)(x).size())
    
    
    #define all(x) (x).begin(),(x).end()
    
    
    #define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
    
    
    #define rep(i,a,b) for (int i=(a),_ed=(b);i<_ed;i++)
    
    
    #define per(i,a,b) for (int i=(b)-1,_ed=(a);i>=_ed;i--)
    
    
    #define pw(x) ((ll(1))<<(x))
    
    
    #define upmo(a,b) (((a)=((a)+(b))%mo)<0?(a)+=mo:(a))
    
    
    #define mmo(a,b) (((a)=1ll*(a)*(b)%mo)<0?(a)+=mo:(a))
    
    void getre(){int x=0;printf("%d\n",1/x);}
    void gettle(){int res=1;while(1)res<<=1;printf("%d\n",res);}
    typedef pair<int,int> pii;
    typedef vector<int> vi;
    typedef vector vpii;
    template<typename T,typename S>inline bool upmin(T&a,const S&b){return a>b?a=b,1:0;}
    template<typename T,typename S>inline bool upmax(T&a,const S&b){return a1:0;}
    template<typename N,typename PN>inline N flo(N a,PN b){return a>=0?a/b:-((-a-1)/b)-1;}
    template<typename N,typename PN>inline N cei(N a,PN b){return a>0?(a-1)/b+1:-(-a/b);}
    template<typename N>N gcd(N a,N b){return b?gcd(b,a%b):a;}
    template<typename N>inline int sgn(N a){return a>0?1:(a<0?-1:0);}
    
    #if ( ( _WIN32 || __WIN32__ ) && __cplusplus < 201103L)
    
      #define lld "%I64d"
    
    #else
    
      #define lld "%lld"
    
    #endif
    
    inline void gn(long long&x){
      int sg=1;char c;while(((c=getchar())<'0'||c>'9')&&c!='-');c=='-'?(sg=-1,x=0):(x=c-'0');
      while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';x*=sg;
    }
    
    inline void gn(int&x){long long t;gn(t);x=t;}
    inline void gn(unsigned long long&x){long long t;gn(t);x=t;}
    inline void gn(double&x){double t;scanf("%lf",&t);x=t;}
    inline void gn(long double&x){double t;scanf("%lf",&t);x=t;}
    inline void gs(char *s){scanf("%s",s);}
    inline void gc(char &c){while((c=getchar())>126 || c<33);}
    inline void pc(char c){putchar(c);}
    
    #ifdef JCVB
    
    
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    
    
    #else
    
    
    #define debug(...) 
    
    
    #endif
    
    typedef long long ll;
    typedef double db;
    inline ll sqr(ll a){return a*a;}
    inline db sqrf(db a){return a*a;}
    const int inf=0x3f3f3f3f;
    const db pi=3.14159265358979323846264338327950288L;
    const db eps=1e-6;

  • 另一个更全的

    /*
    * Package: StandardCodeLibrary.Core
    * */
    //引进常用的头文件并使用std名字空间;
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    
    #include 
    
    using namespace std;
    
    //用于减少代码量的宏;
    
    #define lp for(;;)
    
    
    #define repf(i,a,b) for (int i=(a);i<(b);++i)
    
    
    #define ft(i,a,b) for (int i=(a);i<=(b);++i)
    
    
    #define fdt(i,a,b) for (int i=(a);i>=(b);--i)
    
    
    #define rrepf(i,a,b) fdt(i,(a)-1,b)
    
    
    #define rep(i,n) repf(i,0,n)
    
    
    #define rrep(i,n) rrepf(i,n,0)
    
    
    #define for_each(e,s) for (__typeof__((s).begin()) e=(s).begin();e!=(s).end();++e)
    
    
    #define for_nonempty_subsets(subset,set) for (int subset=set;subset;subset=(subset-1)&(set))
    
    
    #define for_in_charset(i,charset) for (cstr i=(charset);*i;i++)
    
    
    #define whl while
    
    
    #define rtn return
    
    
    #define fl(x,y) memset((x),char(y),sizeof(x))
    
    
    #define clr(x) fl(x,char(0))
    
    
    #define cpy(x,y) memcpy(x,y,sizeof(x))
    
    
    #define sf scanf
    
    
    #define pf printf
    
    
    #define vec vector
    
    
    #define pr pair
    
    
    #define que queue
    
    
    #define prq priority_queue
    
    
    #define itr iterator
    
    
    #define x first
    
    
    #define y second
    
    
    #define pb push_back
    
    
    #define mp make_pair
    
    
    #define ins insert
    
    
    #define ers erase
    
    
    #define lb lower_bound
    
    
    #define ub upper_bound
    
    
    #define rnk order_of_key
    
    
    #define sel find_by_order
    
    
    #define ctz __builtin_ctz
    
    
    #define clz __builtin_clz
    
    
    #define bc __builtin_popcount
    
    
    #define sz(x) (int((x).size()))
    
    
    #define all(x) (x).begin(),(x).end()
    
    
    #define srt(x) sort(all(x))
    
    
    #define uniq(x) srt(x),(x).erase(unique(all(x)),(x).end())
    
    
    #define rev(x) reverse(all(x))
    
    
    #define shf(x) random_shuffle(all(x))
    
    
    #define nxtp(x) next_permutation(all(x))
    
    
    //调试相关的宏;
    
    #ifndef DEBUG
    
    
    #define prt(x) (cerr)
    
    
    #define asrtWA(s) do if(!(s))exit(0);whl(0)
    
    
    #define asrtTLE(s) do if(!(s))whl(1);whl(0)
    
    
    #define asrtMLE(s) do if(!(s))whl(new int);whl(0)
    
    
    #define asrtOLE(s) do if(!(s))whl(1)puts("OLE");whl(0)
    
    
    #define asrtRE(s) do if(!(s))*(int*)0=0;whl(0)
    
    
    #define runtime() (cerr)
    
    
    #define input(in) freopen(in,"r",stdin)
    
    
    #define output(out) freopen(out,"w",stdout)
    
    
    #else
    
    
    #define prt(x) cerr<<"第"<<__LINE__<<"行\t: "<<#x"\t="<<(x)<
    
    
    #define asrtWA(s) do if(!(s))cerr<<"assert("#s")"<
    
    
    #define asrtTLE(s) do if(!(s))cerr<<"assert("#s")"<
    
    
    #define asrtMLE(s) do if(!(s))cerr<<"assert("#s")"<
    
    
    #define asrtOLE(s) do if(!(s))cerr<<"assert("#s")"<
    
    
    #define asrtRE(s) do if(!(s))cerr<<"assert("#s")"<
    
    
    #define runtime() cerr<<"Used: "<
    
    
    #define input(in)
    
    
    #define output(out)
    
    
    #endif
    
    
    //常用数据类型;
    typedef long long int lli;
    typedef double db;
    typedef const char* cstr;
    typedef string str;
    typedef vec<int> vi;
    typedef vec vvi;
    typedef vec vl;
    typedef vec vvl;
    typedef vec<bool> vb;
    typedef vec vvb;
    typedef vec<char> vc;
    typedef vec vvc;
    typedef vec vs;
    typedef pr<int,int> pii;
    typedef pr pll;
    typedef pr pdd;
    typedef vec vpii;
    typedef vec vpll;
    typedef vec vpdd;
    typedef map<int,int> mii;
    typedef mapint> msi;
    typedef map<char,int> mci;
    typedef set<int> si;
    typedef set ss;
    typedef que<int> qi;
    
    //常用常量:int的最大值;lli的最大值;db的误差相关常数;欧拉常数;圆周率;移动向量;取模使用的除数;
    int oo=(~0u)>>1;
    lli ooll=(~0ull)>>1;
    db inf=1e+10;
    db eps=1e-10;
    db gam=0.5772156649015328606;
    db pi=acos(-1.0);
    int dx[]={1,0,-1,0,1,-1,-1,1,0};
    int dy[]={0,1,0,-1,1,1,-1,-1,0};
    int MOD=1000000007;
    
    //常用函数:最大最小值更新;数学相关函数;输入和输出;树状数组;并查集;可合并堆;
    template<typename type>inline bool cmax(type& a,const type& b){rtn atrue:false;}
    template<typename type>inline bool cmin(type& a,const type& b){rtn btrue:false;}
    template<typename type>inline type sqr(const type& x){rtn x*x;}
    template<typename type>inline type mod(const type& x){rtn x%MOD;}
    inline int sgn(const db& x){rtn (x>+eps)-(x<-eps);}
    inline int dbcmp(const db& a,const db& b){rtn sgn(a-b);}
    template<typename type>inline pr operator-(const pr& x){rtn mp(-x.x,-x.y);}
    template<typename type>inline pr operator+(const pr& a,const pr& b){rtn mp(a.x+b.x,a.y+b.y);}
    template<typename type>inline pr operator-(const pr& a,const pr& b){rtn mp(a.x-b.x,a.y-b.y);}
    template<typename type>inline pr operator*(const pr& a,const type& b){rtn mp(a.x*b,a.y*b);}
    template<typename type>inline pr operator/(const pr& a,const type& b){rtn mp(a.x/b,a.y/b);}
    template<typename type>inline pr& operator-=(pr& a,const pr& b){rtn a=a-b;}
    template<typename type>inline pr& operator+=(pr& a,const pr& b){rtn a=a+b;}
    template<typename type>inline pr& operator*=(pr& a,const type& b){rtn a=a*b;}
    template<typename type>inline pr& operator/=(pr& a,const type& b){rtn a=a/b;}
    template<typename type>inline type cross(const pr& a,const pr& b){rtn a.x*b.y-a.y*b.x;}
    template<typename type>inline type dot(const pr& a,const pr& b){rtn a.x*b.x+a.y*b.y;}
    template<typename type>inline type gcd(type a,type b){if(b)whl((a%=b)&&(b%=a));rtn a+b;}
    template<typename type>inline type lcm(type a,type b){rtn a*b/gcd(a,b);}
    inline lli bin_pow(lli x,lli y){lli z=1;whl(y){if(y&1)z=mod(z*x);x=mod(sqr(x)),y>>=1;}rtn z;}
    template<typename istream,typename first_type,typename second_type>inline istream& operator>>(istream& cin,pr& x){rtn cin>>x.x>>x.y;}
    template<typename ostream,typename first_type,typename second_type>inline ostream& operator<<(ostream& cout,const pr& x){rtn cout<" "<template<typename istream,typename type>inline istream& operator>>(istream& cin,vec& x){rep(i,sz(x))cin>>x[i];rtn cin;}
    template<typename ostream,typename type>inline ostream& operator<<(ostream& cout,const vec& x){rep(i,sz(x))cout<1==sz(x)?"":" ");rtn cout;}
    inline ostream& pdb(int prcs,db x){rtn cout<0);}
    template<typename type>inline void bit_inc(vec& st,int x,type inc){whl(x1;}
    template<typename type>inline type bit_sum(const vec& st,int x){type s=0;whl(x>=0)s+=st[x],x=(x&(x+1))-1;rtn s;}
    template<typename type>inline type bit_kth(const vec& st,int k){int x=0,y=0,z=0;whl((1<<(++y))<=sz(st));rrep(i,y){if((x+=1<sz(st)||z+st[x-1]>k)x-=1<else z+=st[x-1];}rtn x;}
    inline void make_set(vi& st){rep(i,sz(st))st[i]=i;}
    inline int find_set(vi& st,int x){int y=x,z;whl(y!=st[y])y=st[y];whl(x!=st[x])z=st[x],st[x]=y,x=z;rtn y;}
    inline bool union_set(vi& st,int a,int b){a=find_set(st,a),b=find_set(st,b);rtn a!=b?st[a]=b,true:false;}
    inline void make_set(vpii& st){rep(i,sz(st))st[i]=mp(i,1);}
    inline int find_set(vpii& st,int x){int y=x,z;whl(y!=st[y].x)y=st[y].x;whl(x!=st[x].x)z=st[x].x,st[x].x=y,x=z;rtn y;}
    inline bool union_set(vpii& st,int a,int b){a=find_set(st,a),b=find_set(st,b);rtn a!=b?(st[a].y>st[b].y?st[a].x=b,st[a].y+=st[b].y:st[b].x=a,st[b].y+=st[a].y),true:false;}
    template<typename type>inline void merge(type& a,type& b){if(sz(a)//初始化;
    struct Initializer{
    
    #ifndef DEBUG
    
    Initializer(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}
    
    #else
    
    ~Initializer(){runtime();}
    
    #endif
    
    }initializer;

你可能感兴趣的:(算法,百度,dp)