笔记1

有一部分本人所写,一部分借鉴其他博客,但是忘记备注出处了。侵删

POJ2182

#include<iostream>

#include<cstdio>

using namespace std;

const int maxn=1e5+5;

int s[maxn];

int ans[maxn];

struct node

{

    int l,r,n;

}a[maxn];

void init(int l,int r,int i)

{

    a[i].l=l;

    a[i].r=r;

    a[i].n=r-l+1;

if(l!=r)

    {int mid=(l+r)/2;

    init(l,mid,2*i);

    init(mid+1,r,2*i+1);

    }

 

}

int insert(int i,int x)

{

    a[i].n--;

    if(a[i].l==a[i].r)

    return a[i].l;

    if(a[2*i].n>=x)

    {

        insert(2*i,x);

    }

    else {

        insert(2*i+1,x-a[2*i].n);

    }

}

int main()

{

    int n;

    cin>>n;

    s[1]=0;

    for(int i=2;i<=n;i++)

    {

        cin>>s[i];

    }

    init(1,n,1);

    for(int i=n;i>=1;i--)

    {

        ans[i]=insert(1,s[i]+1);

    }

    for(int i=1;i<=n;i++)

    printf("%d\n",ans[i]);

    return 0;

}

离散化结束。

然后就是一涂色的问题了,假设我们有x条线段,我们就对这x条线段对应的点涂色,最后看一下有多少不同颜色的点就知道有多少是可以看到的了。这里要用一下延迟更新。

只要遍历线段树,一直到叶节点,判断一下叶节点的颜色有几种就可以AC了。

注意:不要用STL,STL确实可以很快速的实现我们的要求,但是直接超时。然而非STL仅仅跑了79ms。

POJ对于STL的限制比较严格。

#include<iostream>

#include<cstdio>

#include<algorithm>

#include<string.h>

#include<stdlib.h>

 

using namespace std;

const int maxn=1e5+10;

int ans;

int tempx[maxn],tempy[maxn];

int tempp[maxn];int treee[maxn];

int dio[10000009];bool lazyy[maxn];

bool vis[maxn];

void update(int now,int l,int r,int al,int ar,int val)

{

    if(l>ar||r<al)//

    {

        return;

    }

    if(al<=l&&ar>=r)

    {

        lazyy[now]=1;

        treee[now]=val;

        return;

    }

    if(lazyy[now])

    {

        lazyy[now]=0;

        lazyy[2*now+1]=lazyy[2*now+2]=1;

        treee[2*now+1]=treee[2*now+2]=treee[now];

 

    }

    int mid=(l+r)/2;

 

    update(2*now+1,l,mid,al,ar,val);//错一点都不行

   

    update(2*now+2,mid+1,r,al,ar,val);

}

void query(int now,int l,int r)

{

    if(l==r)

    {

        if(!vis[treee[now]])

        {

            vis[treee[now]]=1;

            ans++;

 

        }

        return ;//

    }

    if(lazyy[now])

    {

        lazyy[now]=0;

        lazyy[2*now+1]=lazyy[2*now+2]=1;

        treee[2*now+1]=treee[2*now+2]=treee[now];

    }

    int mid=(l+r)/2;

    query(2*now+1,l,mid);//

    query(2*now+2,mid+1,r);//

}

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

        ans=0;

        memset(vis,0,sizeof(vis));

        memset(lazyy,0,sizeof(lazyy));//

        int n;

        cin>>n;int c=0;

        for(int i=0;i<n;i++)

        {

            cin>>tempx[i]>>tempy[i];

            tempp[c++]=tempx[i];

            tempp[c++]=tempy[i];

        }

        sort(tempp,tempp+c);dio[tempp[0]]=0;int k=1;

        for(int i=1;i<c;i++)

        {

            if(tempp[i]!=tempp[i-1])

            {

                dio[tempp[i]]=k++;

            }

        }

        for(int i=0;i<n;i++)

        {

            int x=dio[tempx[i]];

            int y=dio[tempy[i]];

            update(0,0,k-1,x,y,i+1);

        }

        query(0,0,k-1);

        cout<<ans<<endl;

    }

    return 0;

}

Poj3468

#include<iostream>

#include<cstdio>

#include<string.h>

using namespace std;

#define ll long long

const int maxn=2e5+10;

int num[maxn];ll add[maxn<<2],sum[maxn<<2];//

 

void pushup(int rs)

{

    sum[rs]=sum[rs<<1]+sum[rs<<1|1];//

    return;

}

void pushdown(int rs,int l)

{

    if(add[rs])

    {

        add[rs<<1]+=add[rs];

        add[rs<<1|1]+=add[rs];

        sum[rs<<1]+=add[rs]*(l-(l>>1));//

        sum[rs<<1|1]+=add[rs]*(l>>1);

        add[rs]=0;

    }

    return;

}

void build(int l,int r,int now)

{

    if(l==r)

    {

        scanf("%lld",&sum[now]);

       // cout<<sum[now]<<"fe"<<endl;

        return ;//

    }

    int mid=(l+r)/2;

    build(l,mid,now*2);

    build(mid+1,r,now<<1|1);

    pushup(now);

    return;

}

 

void update(int c,int x,int y,int l,int r,int now)

{

    if(x<=l&&r<=y)

    {

        add[now]+=c;

        sum[now]+=(ll)c*(r-l+1);

        return;

    }

    pushdown(now,r-l+1);

    int mid=(l+r)/2;

    if(x<=mid) update(c,x,y,l,mid,now*2);

    if(y>mid) update(c,x,y,mid+1,r,now<<1|1);

    pushup(now);

    return;

}

//ll ans=1;

ll query(int x,int y,int l,int r,int rs)

{

 

    if(l>=x&&y>=r)

    {

        return sum[rs];

 

    }

    pushdown(rs,r-l+1);

    int  mid=(l+r)>>1;

    ll ans=0;//shengmingbianliangdeweizhiyeyouguanxi,否则会影响前面的

    if(x<=mid)   ans+=query(x,y,l,mid,rs<<1);

 

    if(y>mid)    ans+=query(x,y,mid+1,r,rs<<1|1);

    return ans;

}

int main()

{

   // ios::sync_with_stdio(false);

    int t;

   // cin>>t;

   // while(t--)

   // {

        int n;int m;

        scanf("%d%d",&n,&m);//写着写着就忘了怪不得错了

       // cout<<n<<endl;

        memset(num,0,sizeof(num));

        build(1,n,1);

        //int m;

//getchar();

        char s[2];

        while(m--)

        {

            int x,y,z;

            scanf("%s",s);

           // cout<<s<<endl;

           // getchar

            if(s[0]=='C')

            {

                //cin>>x>>y>>z;

                scanf("%d%d%d",&x,&y,&z);

                update(z,x,y,1,n,1);

            }

 

            else

            {

//                ans=0;

 

                scanf("%d%d",&x,&y);

                cout<<query(x,y,1,n,1)<<endl;

 

            }

            getchar();//

 

        }

 

 //   }

    return 0;

}区间修改

POJ2182

#include<iostream>

#include<string.h>

#include<cstdio>

using namespace std;

const int maxn=1e5+5;

int a[maxn],b[maxn];

int c[maxn];

int n;

void add(int i,int val)

{

    for(int j=i;j<=n;j+=j&(-j))

    {

        a[j]+=val;

    }

}

int count(int x)

{//用次数计数表示第几个,不是区间修改

    int ans=0;

    while(x)

    {

        ans+=a[x];

        x-=x&(-x);

    }

    return ans;

}

int find(int pos)

{

    int l=1,r=n;int p=0;

    while(l<=r)

    {

        int mid=(l+r)/2;

    if(count(mid)>=pos)

    {

        p=mid;//写着写着就忘了自己在写什么了

        r=mid-1;

    }

    else l=mid+1;

 

    }

    return p;

 

 

}

int main()

{

    //int n;

    cin>>n;

    add(1,1);

    for(int i=2;i<=n;i++)

    {

        scanf("%d",&c[i]);//意义不同,弄混了

        add(i,1);

    }

    for(int i=n;i>=1;i--)

    {

        int pos=find(c[i]+1);

        b[i]=pos;

        add(pos,-1);

    }

    for(int i=1;i<=n;i++)

    {

        cout<<b[i]<<endl;

    }

    return 0;

 

}

分析:不难发现要从后往前确定每头牛的身高,这样每头牛的身高就是1~n中没被选过的第a[i]+1大的数(因为有a[i]头比自己矮),那么我们只需用树状数组维护一个01序列,没选过的数标为1,每次查询时二分mid,通过树状数组ask(mid)计算前mid个数有几个为1即没被选过的,直到找到a[i]+1。

主要是有顺序直接找第几大的,0,1又恰好可以表示是否被取走,正好符合区间求和,和单点更新。

Poj2299

相邻的用逆序对。也可以用树状数组,诡异了的说。反正是逆序对的个数就是最小操作数。

因为一定可以转化为相邻的。要证吗?不知道。最小操作数应该也只有逆序对了。

树状数组主要用来单点更新,区间求和,求逆序对咋用啊,求总的话,因该是整个区间求和,那么单个应该有一定的意义,每一个地方和前面的逆序对个数。那么单点更新该怎么用,应该是前面假设都单调递增,出现一个逆序的,那么单调递增的后面的都是逆序对,加上去就可以了,如何找到第一个逆序的呢,序号肯定需要,数也需要,因为要比较嘛,那么如何从前面走一遍?二分走一遍,因为是有顺序的,且复杂度应该还要降低,那么只能是二分了。

那么需要逆序对个数的数组,和输入数据的数组,如何建树呢。不需要。初始化?为0.

那么接下来我写的第一道题开始了~

可是并不是本身就有序的,刚刚搞错了。如何使其有序,要插到中间去才行。每一个往后诺以为显然不可取,那么座标改变呢,也相当于N的复杂度了吧。到底咋做啊。所以这思路不对啊。

每一次加进去的时候统计数量,

 

1.解释为什么要有离散的这么一个过程?

 

    刚开始以为999.999.999这么一个数字,对于int存储类型来说是足够了。

 

    还有只有500000个数字,何必要离散化呢?

 

    刚开始一直想不通,后来明白了,后面在运用树状数组操作的时候,

 

    用到的树状数组C[i]是建立在一个有点像位存储的数组的基础之上的,

 

    不是单纯的建立在输入数组之上。

 

    比如输入一个9 1 0 5 4,那么C[i]树状数组的建立是在,

 

 

 

    数据:9 1 0 5 4  p[i].val

 

    编号:1 2 3 4 5  p[i].oder = i*************

 

    sort

 

    数据:0 1 4 5 9

 

    编号:3 2 5 4 1

 

    顺序:1 2 3 4 5

 

 

 

    a[p[i].编号] = 顺序号;**********************

 

   

 

    a[3] = 1<--0;

 

    a[2] = 2<--1;

 

    a[5] = 3<--4;

 

    a[4] = 4<--5;

 

    a[1] = 5<--9;

 

     

 

    a[]={ 5 2 1 4 3 }

 

 

 

    新号:1 2 3 4 5

 

    值  :

 

 

 

    下标 0 1 2 3 4 5 6 7 8 9

 

    数组 1 1 0 0 1 1 0 0 0 1

 

    现在由于999999999这个数字相对于500000这个数字来说是很大的,

 

    所以如果用数组位存储的话,那么需要999999999的空间来存储输入的数据。

 

    这样是很浪费空间的,题目也是不允许的,所以这里想通过离散化操作,

 

    使得离散化的结果可以更加的密集。

 

    简言之就是开一个大小为这些数的最大值的树状数组

 

2. 怎么对这个输入的数组进行离散操作?

 

   离散化是一种常用的技巧,有时数据范围太大,可以用来放缩到我们能处理的范围;

 

   因为其中需排序的数的范围0---999 999 999;显然数组不肯能这么大;

 

   而N的最大范围是500 000;故给出的数一定可以与1.。。。N建立一个一一映射;

 

   (1)当然用map可以建立,效率可能低点;

 

   (2)这里用一个结构体

 

   struct Node

 

   {

 

      int val,pos;

 

   }p[510000];和一个数组a[510000];

 

 

 

   其中val就是原输入的值,pos是下标;

 

   然后对结构体按val从小到大排序;

 

 

 

   此时,val和结构体的下标就是一个一一对应关系,

 

   而且满足原来的大小关系;

 

 

 

   for(i=1;i<=N;i++)

 

   a[p[i].pos]=i;

 

 

 

   然后a数组就存储了原来所有的大小信息;

 

   比如 9 1 0 5 4 ------- 离散后aa数组

 

   就是 5 2 1 4 3;

 

   具体的过程可以自己用笔写写就好了。

 

 

 

3. 离散之后,怎么使用离散后的结果数组来进行树状数组操作,计算出逆序数?

 

    如果数据不是很大, 可以一个个插入到树状数组中,

 

    每插入一个数, 统计比他小的数的个数,

 

    对应的逆序为 i- sum( a[i] ),

 

    其中 i 为当前已经插入的数的个数,

 

    sum( a[i] )为比 a[i] 小的数的个数,

 

    i- sum( a[i] ) 即比 a[i] 大的个数, 即逆序的个数

 

    但如果数据比较大,就必须采用离散化方法

 

    假设输入的数组是9 1 0 5 4, 离散后的结果a[] = {5,2,1,4,3};

 

在离散结果中间结果的基础上,那么其计算逆序数的过程是这么一个过程。

 

1.输入5,   调用add(5, 1),把第5位设置为1

 

1 2 3 4 5

 

0 0 0 0 1

 

计算1-5上比5小的数字存在么? 这里用到了树状数组的sum(5) = 1操作,

 

现在用输入的下标1 -sum(5) = 0 就可以得到对于5的逆序数为0。

 

2. 输入2, 调用add(2, 1),把第2位设置为1

 

1 2 3 4 5

 

0 1 0 0 1

 

计算1-2上比2小的数字存在么? 这里用到了树状数组的sum(2) = 1操作,

 

现在用输入的下标2 - sum(2) = 1 就可以得到对于2的逆序数为1。

 

3. 输入1, 调用add(1, 1),把第1位设置为1

 

1 2 3 4 5

 

1 1 0 0 1

 

计算1-1上比1小的数字存在么? 这里用到了树状数组的sum(1) = 1操作,

 

现在用输入的下标 3 -sum(1) = 2 就可以得到对于1的逆序数为2。

 

4. 输入4, 调用add(4, 1),把第5位设置为1

 

1 2 3 4 5

 

1 1 0 1 1

 

计算1-4上比4小的数字存在么? 这里用到了树状数组的sum(4) = 3操作,

 

现在用输入的下标4 - sum(4) = 1 就可以得到对于4的逆序数为1。

 

5. 输入3, 调用add(3, 1),把第3位设置为1

 

1 2 3 4 5

 

1 1 1 1 1

 

计算1-3上比3小的数字存在么? 这里用到了树状数组的sum(3) = 3操作,

 

现在用输入的下标5 - sum(3) = 2 就可以得到对于3的逆序数为2。

 

6. 0+1+2+1+2 = 6 这就是最后的逆序数

 

分析一下时间复杂度,首先用到快速排序,时间复杂度为O(NlogN),

 

后面是循环插入每一个数字,每次插入一个数字,分别调用一次add()和sum()

 

外循环N, add()和sum()时间O(logN) => 时间复杂度还是O(NlogN)

这说明等价的但是不一定就能有一样的简单。

输入的顺序也被用到了。

 

大部分都是看着网上博客自己敲了一遍,中途波折异常,不过还是完成了几道题吧。

之前还做了一道图论的模板题,一开始果断放弃,然后补上了。

Zoo

Description

 

现在你是动物园的一名员工,负责整个园区人行道的布局,目前所有人行道都是单向道路。

这些路径将动物园分成了若干个区域,每个区域内存在11个或多个景点

在同一个区域内的任意两个景点之间可以互相到达,但是当你从一个区域走到另一个区域时

你就再也不能回到之前走过的区域,并且存在一条路径可以走遍所有的区域。

这样的设计可以控制动物园的游客流量。(输入的数据保证满足这些条件)

现在你可以尽可能的多添加边,要求不能有重边和自环

并且需要满足如果在之前uu不可到达vv,那么添加边之后uu还是不可以到达vv

求最多能添加的边数。

Input

 

输入第一行为正整数nn,表示景点数目(1≤n≤2500)(1≤n≤2500)

接下来输入nn行,每行nn个整数Map_{ij}Mapij​ (Map_{ij}=0\ or\ Map_{ij}=1)(Mapij​=0 or Mapij​=1)

Map_{ij}Mapij​11,表示iijj之间存在单向边<i,j><i,j>,为00则表示不存在。

Output

 

输出一个整数表示最多能添加的边

Sample Input 1 

7

0 1 0 0 0 0 0

0 0 1 0 1 0 0

1 0 0 1 0 0 0

1 0 0 0 0 0 0

0 0 0 0 0 1 0

0 0 0 0 0 0 1

0 0 0 0 1 0 0

Sample Output 1

21

Sample Input 2 

5

0 1 0 0 0

0 0 1 0 0

0 0 0 1 0

0 0 0 0 1

0 0 0 0 0

Sample Output 2

6

Sample Input 3 

2

0 1

1 0

Sample Output 3

0

Hint

输入数据量较大,建议使用高效的输入输出方式

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int a[2510][2510];
  4. vector<int> g[2510];
  5. const int maxn=2510;
  6. int low[maxn],pre[maxn],col[maxn];int vis[maxn],ru[maxn];
  7. stack<int>q;int topo[maxn];//注意栈
  8. int deep,ccnt,n;
  9. void dfs(int u){
  10.   pre[u]=low[u]=++deep;
  11. //       vis[u]=1;
  12.   q.push(u);
  13.   int sz=g[u].size();
  14.   for(int i=0;i<sz;i++){
  15.          int v=g[u][i];
  16.          if(!pre[v]){
  17.                  dfs(v);
  18.                  low[u]=min(low[u],low[v]);
  19.          }
  20.          else if(!col[v]){
  21.                  low[u]=min(low[u],pre[v]);
  22.          }
  23.   }
  24.  
  25.   if(low[u]==pre[u]){
  26.          ccnt++;
  27.          for(;;){
  28.                  int x=q.top();
  29.                  q.pop();
  30.                  col[x]=ccnt;
  31.          //      col[x]=cnt;
  32.                  vis[ccnt]++;
  33.                  if(x==u) break;
  34.          }
  35.   }
  36. }
  37. void find_scc(){
  38.   deep=ccnt=0;
  39.   memset(pre,0,sizeof(pre));
  40.   memset(vis,0,sizeof(vis));
  41.   for(int i=1;i<=n;i++){
  42.          if(!pre[i]) dfs(i);
  43.   }
  44. }
  45. vector<int>gg[maxn];
  46. int main(){
  47. //       int n;
  48.   cin>>n;int tot=0;
  49.   for(int i=1;i<=n;i++){
  50.          for(int j=1;j<=n;j++){
  51.                  cin>>a[i][j];
  52.                  if(a[i][j]){
  53.                          g[i].push_back(j);tot++;
  54.                  }
  55.          }
  56.   }
  57.   //cout<<tot<<endl;
  58.   find_scc();
  59.   for(int i=1;i<=n;i++){
  60.          for(int j=0;j<g[i].size();j++){
  61.                  int v=g[i][j];//
  62.                  if(col[i]!=col[v]){
  63.                    gg[col[i]].push_back(col[v]);//
  64.                          ru[col[v]]++;
  65.                  }
  66.          }
  67.   }
  68.   queue<int>qq;
  69.   for(int i=1;i<=ccnt;i++){
  70.          if(!ru[i]) qq.push(i);
  71.   }
  72.   int cnt=0;
  73.   while(!qq.empty()){
  74.          int y=qq.front();qq.pop();
  75.          topo[++cnt]=y;
  76.          for(int i=0;i<gg[y].size();i++){
  77.                  int v=gg[y][i];
  78.                  if(--ru[v]==0) qq.push(v);
  79.          }      
  80.   }
  81.   int ans=0;
  82.   for(int i=1;i<=ccnt;i++){
  83.          ans+=vis[i]*(vis[i]-1);
  84.   //      cout<<ans<<endl;
  85.          for(int j=i+1;i<=cnt&&j<=cnt;j++){
  86.                  ans+=vis[topo[i]]*vis[topo[j]];
  87.          }
  88.   }
  89.   cout<<ans-tot<<endl;
  90.   return 0;
  91.  
  92. }

终于做完了这道缩点和拓扑排序的题了。

然后看了这篇博客挺好的:https://www.cnblogs.com/stxy-ferryman/p/7779347.html

#include <assert.h>
void assert( int expression );

#include <stdio.h>

#include <assert.h>

#include <stdlib.h>

int main( void )

{

       FILE *fp;

   

       fp = fopen( "test.txt", "w" );//以可写的方式打开一个文件,如果不存在就创建一个同名文件

       assert( fp );                           //所以这里不会出错

       fclose( fp );

   

       fp = fopen( "noexitfile.txt", "r" );//以只读的方式打开一个文件,如果不存在就打开文件失败

       assert( fp );                           //所以这里出错

       fclose( fp );                           //程序永远都执行不到这里来

       return 0;

}

Hdu6492

 

#include<bits/stdc++.h>

using namespace std;

#define ll long long

const int nn=3225;

ll f[nn];

ll a,b,c;int n,m,k;

void pre()

{

    int shu=(n+m+k+20);

   // cout<<shu<<endl;

    for(int i=0;i<=shu;i++)

    f[i]=(ll)1<<60;

    f[0]=(ll)0;

    for(int i=2;i<=shu;i++)

    {

        f[i]=min(f[i],f[i-2]+a);

      //  cout<<i<<" "<<f[i]<<"fe"<<endl;

    }

    for(int i=3;i<=shu;i++)

    {

        f[i]=min(f[i],f[i-3]+b);

    }

    for(int i=shu-1;i>=0;i--)

    {

        f[i]=min(f[i],f[i+1]);//要倒过来

    }

 

}

 

int main()

{

    int t;

   //pre();

    cin>>t;

//pre();

    while(t--)

    {

 

        cin>>n>>m>>k>>a>>b>>c;

        pre();

      //  cout<<f[4]<<"h"<<endl;

        ll res=((ll)1<<60);

        for(int i=0;i<=k;i++)

        {

            res=min(res,(ll)c*i+f[n+k-i]+f[m+k-i]);

        //    cout<<res<<"f"<<endl;

        //    cout<<n+k-i<<"fee"<<f[n+k-i]<<endl;

 

        }

        cout<<res<<endl;

 

    }

    return 0;

}

首先,题目很明显可以用揹包,但是我忘记了,原因是我没做足够的题目,或者认真。

完全是可以知道哪里出错的。也可以逐步缩小范围判断。

有的时候根本不知道错在哪里,而这种时候重新写一遍就可以对,不过很神奇的是,思路对,又会有哪个细节出了问题。

memset(a,127,sizeof(a));

即得到无穷大。

memset(a,128,sizeof(a));

即得到无穷小,与上述的值互为相反数。

memset(a,60,sizeof(a));

即近似为第一个式子的数值的一半。

memset(a,0,sizeof(a));赋值0

memset(a,-1,sizeof(a));赋值-1

hdu6494

#include<bits/stdc++.h>

using namespace std;

int f[10010][12][12];

struct node

{

    int x,y,z;

}temp;

node fff(int i,int j)

{

    if(i==11||j==11)

    {

        temp.z=1;

        temp.x=0;

        temp.y=0;

    }

    else if(i==10&&j==10)

    {

        temp.z=0;

        temp.x=9;

        temp.y=9;

    }

    else

    {

        temp.z=0;

        temp.x=i;

        temp.y=j;

    }

    return temp;

}

char s[100010];

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

        cin>>s;

        int len=strlen(s);

        memset(f,128,sizeof(f));//

        f[0][0][0]=0;//

        for(int i=1;i<=len;i++)

        {

            for(int j=0;j<=10;j++)

            {

                for(int k=0;k<=10;k++)

                {

                   // if(f[i-1][j][k]<(1<<30))//

                    if(s[i-1]=='A'||s[i-1]=='?')

                    {

                        node temp=fff(j+1,k);

                        f[i][temp.x][temp.y]=max(f[i-1][j][k]+temp.z,f[i][temp.x][temp.y]);

                        //cout<<f[i][temp.x][temp.y]<<"temp"<<endl;

                    }

                    if(s[i-1]=='B'||s[i-1]=='?')

                    {

                        node temp=fff(j,k+1);

                        f[i][temp.x][temp.y]=max(f[i-1][j][k]+temp.z,f[i][temp.x][temp.y]);

                    }

                }

            }

        }int res=0;

        for(int i=0;i<=10;i++)

        {

            for(int j=0;j<=10;j++)

            {

                res=max(res,f[len][i][j]);

             //   cout<<f[len][i][j]<<endl;

            }

        }

        cout<<res<<endl;

    }

    return 0;

}

动态规划,大转为小,然后就这样。

6495

#include<bits/stdc++.h>

using namespace std;

const int maxn=1005;

#define ll long long

ll f[maxn][maxn];

int a[maxn],b[maxn],c[maxn];

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

 

 

        int n,cc;

        cin>>n>>cc; //f[0][0]=cc;

        for(int i=1;i<=n;i++)//初始值

        {

            cin>>a[i]>>b[i]>>c[i];

 

        }

        for(int i=0;i<=n;i++)

        {

            for(int j=0;j<=n;j++)

            f[i][j]=0;

        }

        f[0][0]=cc;

        for(int i=0;i<=n-1;i++)

        {

 

            for(int j=0;j<=i;j++)

            {

                if(f[i][j])//

                {

 

 

                f[i+1][j]=max(f[i][j]+c[i+1],f[i+1][j]);

                if(min(f[i][j],b[i+1]*1ll)>a[i+1])

                {

                    f[i+1][j+1]=max(f[i+1][j+1],min(f[i][j],b[i+1]*1ll)-a[i+1]+c[i+1]);

                }

                }

            }

        }

        for(int i=n;i>=0;i--)

        {

 

            if(f[n][i])

            {

               // cout<<f[n][i]<<endl;

                cout<<i<<endl;

                break;

            }

        }

 

    }

    return 0;

 

}

转移方程细节问题。

//6496

Hdu4841

#include<bits/stdc++.h>

using namespace std;

vector<int>q;//insert

int main()

{

    int n;

    int m;

    while(cin>>n>>m)

    {

       // cin>>n>>m;

       q.clear();

    for(int i=0;i<2*n;i++)

    {

        q.push_back(i);

    }

    int pos=0;

    for(int i=0;i<n;i++)

    {

         pos=(pos+m-1)%q.size();

        q.erase(q.begin()+pos);//

    }

   // for(int i=0;i<n;i++)

   // {

     //   cout<<q[i]<<" ";

   // }

    int j=0;

    for(int i=0;i<2*n;i++)

    {

        if(i&&!(i%50)) cout<<endl;

        //int j=0;

        if(j<q.size()&&i==q[j])

        {

            cout<<"G";j++;

        }

         else cout<<"B";

    }

    cout<<endl;cout<<endl;

    }

    return 0;

}

Hdu1062

#include<bits/stdc++.h>

using namespace std;

 

int main()

{

    int t;

    cin>>t;getchar();

        while(t--)

    {

        stack<char> s;//为了不要每次都初始赋值而定义

                char ch;

        while(1)

        {

            ch =getchar();//一个个读取字符

            if(ch==' '||ch=='\n'||ch=='EOF')

            {

                while(!s.empty())

                {

                    cout<<s.top();

                    s.pop();

 

                }

                if(ch=='\n'||ch=='EOF')

                {

                    break;

                }

                printf(" ");

            }

            else

            {

                s.push(ch);

            }

        }

        cout<<endl;

    }

    return 0;

}

Hdu1237

对于中缀表达式的运算一般要转化成后缀表达式再作运算,开两个栈,一个作为操作数栈StackDigital,一个作为操作符栈StackOperator。

1.定义一个函数判定优先级:# 的优先级最低,为0,+ 和 - 的级别相同且高于 #,标为1,* 和 / 的级别相同且高于 + 和 - ,标志为2,

2.先往运算符栈放入一个 # (标定界限),表达式最后也加一个 #( (标定界限)),

3.遍历表达式,若读到数字,则以数字类型输入,直接放到操作数栈,若读到的是运算符,则比较读到的运算符与运算符栈顶符号的级别,

若比栈顶的高,则入栈,否则,从数栈取两个操作数根据操作符栈顶的操作进行运算,再把结果压入数栈,刚刚读到的运算符再与现在运算符栈

顶元素的级别进行比较……最后数剩下的一个元素,就是结果。

注意#include<bits/stdc++.h>

using namespace std;

int main()

{

    int n;

    cin>>n;//必须是char   isdigit才可以检查出一位是否为0~9

    if(isdigit(n)) cout<<n<<endl;

    else cout<<n<<"f"<<endl;

    return 0;//

}

Sscanf:

3、字符串转数字:使用sscanf()函数

char str[]="1234321";
int a;
sscanf(str,"%d",&a);
.............
char str[]="123.321";
double a;
sscanf(str,"%lf",&a);
.............
char str[]="AF";
int a;
sscanf(str,"%x",&a); //16
进制转换成10进制
 

#include<bits/stdc++.h>

using namespace std;

int top1,top2;

double dig[300];

char str[300],cao[300];

int priority(char op)

{

  //  int i;

    switch(op)

    {

        case '+':

        return 1;

        case '-':

        return 1;

        case '*':

        return 2;

        case '/':

        return 2;

        case '#':

        return 0;

        default :

        return -1;//

    }

}

double run(double x,double y,char op)

{

    if(op=='*') return x*y;

    else if(op=='/') return (double)x*1.0/y;

    else if(op=='+') return x+y;

    else if(op=='-') return x-y;

    else return -1;

}

double temp;

double calc()

{

    top1=top2=-1;//

    int i;int n=strlen(str);//cout<<n<<"n"<<endl;

    str[n++]='#';//teshu

    cao[++top2]='#';

  //  dig[top1++]='#';

    for(i=0;i<n;i++)

    {

      //  cout<<"full"<<str[i]<<endl;

        if(str[i]==' ') continue;

      //  cout<<str[i]<<"str"<<endl;

 

        if(isdigit(str[i]))

        {

      //  cout<<str[i]<<"str"<<endl;

 

        sscanf(str+i,"%lf",&temp);//

        dig[++top1]=temp; // cout<<temp<<endl;

        while(isdigit(str[i+1])) i++;

 

        }

        else

        {

            while(priority(cao[top2])>=priority(str[i]))

            {

                if(str[i]=='#'&&cao[top2]=='#')

                return dig[top1];

                double y=dig[top1--];//double注意

                double x=dig[top1--];

                char op=cao[top2--];//

                dig[++top1]=run(x,y,op);

 

            }

            cao[++top2]=str[i];

        }

 

    }

 

    return dig[top1];

}

int main()

{

    while(gets(str)!=NULL&&strcmp(str,"0")!=0)//

    {

       // cout<<str<<endl;

        //cout<<calc()<<endl;

        printf("%.2lf\n",calc());

    }

    return 0;

}
另外也可以使用atoi(),atol(),atof

 

Hdu1702

#include<bits/stdc++.h>

using namespace std;

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

        int n;int num ;

        string str1,str2;

        cin>>n>>str1;

        stack<int> s;

        queue<int> q;

        while(n--)

        {

            if(str1=="FIFO")

        {

            cin>>str2;

            if(str2=="IN")

            {

                cin>>num ;

                q.push(num);

 

            }

            else

            {

                    if(q.empty())

                    cout<<"None"<<endl;

                    else

                    {

                        cout<<q.front()<<endl;

                        q.pop();

                    }

            }

        }

        else

        {

            cin>>str2;

            if(str2=="IN"){cin>>num; s.push(num);}

            else

            {

                if(s.empty()) cout<<"None"<<endl;

                else {

                cout<<s.top()<<endl;

                s.pop();

                }

            }

 

 

        }

        }

    }

    return 0;

}

 

Hdu1276

  • STL的 list :双向链表。它的内存空间不必连续,通过指针来进行数据的访问,高效率地在任意地方删除和插入,插入和删除操作是常数时间。

#include<bits/stdc++.h>

using namespace std;

int  main()

{

    int t;

    cin>>t;int n;

    while(t--)

    {

        cin>>n;

        list<int> mylist;//

        list<int> ::iterator it;

        int k=2;

        for(int i=1;i<=n;i++)

        {

            mylist.push_back(i);//push_back

        }

        while(mylist.size()>3)

        {

            int i=1;

            for(it=mylist.begin();it!=mylist.end();)

            {

                if(i++%k==0)

                {

                    it=mylist.erase(it);//must have "value" returned

 

 

                }

                else it++;

            }

            k=k==2?k=3:k=2;

        }

        for(it=mylist.begin();it!=mylist.end();it++)

        {

            if(it!=mylist.begin()) cout<<" ";

            cout<<*it;

        }

        cout<<endl;

    }

    return 0;

}

要学会用mylist

 

Hdu2094

#include<bits/stdc++.h>

using namespace std;

int main()

{

    int n;

    set<string> a,b;

    string str1,str2;

    while(cin>>n&&n)

    {

        while(n--)

        {

            cin>>str1>>str2;

        a.insert(str1); a.insert(str2);

        b.insert(str2);

        }

        if(a.size()-b.size()==1)

        {

            cout<<"Yes"<<endl;

        }

        else

        {

            cout<<"No"<<endl;

        }

    a.clear();b.clear();//

    }

    return 0;

}

Set灵活使用vital

 

Hdu2684

#include<bits/stdc++.h>

using namespace std;

int main()

{

    int n,m,p;int d;

    map<string,int> shop;string s,ss;

    while(cin>>n&&n)

    {d=n;

    shop.clear();

    while(n--)

    {

        cin>>s;}

 

        cin>>m; n=d;

 

        while(m--)

        {

            while(n--)

            {

                cin>>p>>s;

                shop[s]+=p;

 

            }

n=d;

        map<string,int> ::iterator it;int rank=1;

        for(it=shop.begin();it!=shop.end();it++)

        if(it->second>shop["memory"])//

        {

            rank++;

        }

        cout<<rank<<endl;

        }

 

  //  shop.clear();

    }

    return 0;

}

Hdu1027

#include<bits/stdc++.h>

using namespace std;

int a[1001];

int main()

{

    int n,m;

    while(cin>>n>>m)

    {

        for(int i=1;i<=n;i++)

        a[i]=i;int b=1;

        do

        {

 

           if(b==m)

           {

               break;

           }

           else b++;

 

 

        }while( next_permutation(a+1,a+n+1));

        for(int i=1;i<n;i++)

        {

            cout<<a[i]<<" ";

 

        }

        cout<<a[n]<<endl;

    }

    return 0;

}

看叉了

STL 嘛,还是要熟练运用的。然后忘了 还讲了什么课了,没找到其他的了。

POJ3981

#include<iostream>

using namespace std;

int main()

{

    string s;int pos;

    while(getline(cin,s))//

    {

        while((pos=s.find("you"))!=-1)//有返回值

        {

            s.replace(pos,3,"we");//replace

 

        }

        cout<<s<<endl;

    }

    return 0;

}

Hdu1062

这回自己写一遍

#include<iostream>

#include<bits/stdc++.h>

using namespace std;

 

int main()

{

    int t;

    cin>>t;getchar();

    while(t--)

    {

        char ch;

        stack<char> q;

        while(1)

        {

            ch=getchar();

            if(ch==' ')

            {

                while(!q.empty())

                {

                    cout<<q.top();

                    q.pop();

                }

                cout<<" ";

            }

            else if(ch=='\n'||ch==EOF)

            {

                while(!q.empty())

                {

                    cout<<q.top();

                    q.pop();

                }

                break;

            }

            else

            {

                q.push(ch);

            }

 

        }

//        q.clear();

cout<<endl;

    }

    return 0;

}//字符串反转,使用栈,同时注意格式

Hdu6013,字符串反转,尺取法

分治法求(PPT上面的代码有必要敲一遍,原因略)

int fastpow(int a,int n)

{

 

    if(n==1) return a;

    int temp=fastpow(a,n/2);

    if(n%2==1)

    temp=temp*temp*a;

    else temp=temp*temp;

    return temp;

}

快速幂

int fastpow(int a,int n)

{

    int base=a;

    int res=1;

    while(n)

    {

        if(n&1) res*=base;

        base=base*base;

        n>>=1;

    }

    return res;

}

矩阵快速幂

const int modn=1e4;

const int maxn=2;

struct matrix

{

    int m[maxn][maxn];

    matrix()

    {

        memset(m,0,sizeof(m));//

    }

};

matrix multi(matrix a,matrix b)

{

    matrix res;

    for(int i=0;i<maxn;i++)

    {

        for(int j=0;j<maxn;j++)

        {

            for(int k=0;k<maxn;k++)

            {

                res.m[i][j]=(res.m[i][j]+a.m[i][k]*b.m[k][j])%modn;

            }

        }

    }

    return res;

   

}

matix fastpow(matrix s,int n)

{

    matrix res;

    for(int i=0;i<maxn;i++)

    res.m[i][i]=1;

    while(n)

    {

        if(n&1) res=multi(res,s);

        s=multi(s,s);

        n>>=1;

    }

    return res;

}

Gcd

int gcd(int a,int b)

{

    return b==0?a;gcd(b,a%b);

}

int lcm(int a,int b)

{

    return a/gcd(a,b)*b;

}

扩展欧几里得算法:

void extend_gcd(int a,int b,int &x,int &y)

{

    if(b==0)

    {

        x=1;y=0;

        return;

    }

    extend_gcd(b,a%b,x,y);

    int temp=x;

    x=y;

    y=temp-(a/b)*y;

   

}

 

Hdu1042

Hdu 1047

Hdu1063

Hdu1316

Hdu5666

Hdu 5686

Hdu5584

Hdu 1262

Hdu 2710

Hdu 3792

Hdu 3826

Hdu 6069

Hdu1205

Hdu 5917

Hdu 6152

Hdu 2032

Hdu 2841

Hdu 4135

Hdu 4497

Hdu 5155

Poj 3070

Hdu 2041

Hdu 1028

#include<bits/stdc++.h>

using namespace std;

int a[122];

int b[122];

 

int main()

{

    int n;

    while(~scanf("%d",&n))

    {

        for(int i=0;i<=n;i++)

        {

            a[i]=1;b[i]=0;

        }

        for(int i=2;i<=n;i++)

        {

            for(int j=0;j<=n;j++)

            {

                for(int k=0;k+j<=n;k+=i)

                {

                    b[k+j]+=a[j];

                }

            }

            for(int j=0;j<=n;j++)

            {

                a[j]=b[j];

                b[j]=0;

            }

        }

       // for(int i)

       cout<<a[n]<<endl;

    }

    return 0;

}

母函数

Hdu 1521

指数型母函数

#include<bits/stdc++.h>

using namespace std;

double a[12],b[12];

int c[12];

double jie(int n)

{

    double res=1.0;

    for(int i=1;i<=n;i++)

    res*=i;

    return res;

 

}

int main()

{

    int n;

    int m;

    while(cin>>n>>m)

    {

        for(int i=1;i<=n;i++)

        cin>>c[i];

        memset(a,0,sizeof(a));

        memset(b,0,sizeof(b));

        for(int i=0;i<=c[1];i++)

        {

            a[i]=1.0/jie(i);// cout<<a[i]<<endl;

            b[i]=0;

        }

        for(int i=2;i<=n;i++)

        {

            for(int j=0;j<=m;j++)//

            {

                for(int k=0;k<=c[i]&&(j+k<=m);k++)

                {

                    b[j+k]+=a[j]/jie(k);//jiecheng

                   // cout<<a[]

                }

            }

            for(int i=0;i<=m;i++)

            {

                a[i]=b[i];

                b[i]=0;

            }

 

        }

        //cout<<a[m]<<endl;

      //  cout<<jie(m)<<endl;

       // cout<<m<<endl;

        //cout<<int(a[m]*jie(m))<<endl;//shipailieshu

        printf("%.0lf\n",a[m]*jie(m));

    }

    return 0;

}

取整和%.0lf区别是有的,最有可能是,%.0lf为四舍五入

Hdu 2067

       在做ACM题时,经常都会遇到一些比较大的整数。而常用的内置整数类型常常显得太小了:其中long int 范围是[-2^31,2^31),即-2147483648~2147483647。而unsigned范围是[0,2^32),即0~4294967295。也就是说,常规的32位整数只能够处理40亿以下的数。

那遇到比40亿要大的数怎么办呢?这时就要用到C++64位扩展了。不同的编译器对64位整数的扩展有所不同。基于ACM的需要,下面仅介绍VC6.0g++编译器的扩展。
VC6.064位整数分别叫做__int64unsigned __int64,其范围分别是[-2^63, 2^63)[0,2^64),即-9223372036854775808~92233720368547758070~18446744073709551615(1800亿亿)。对64位整数的运算与32位整数基本相同,都支持四则运算与位运算等。当进行64位与32位的混合运算时,32位整数会被隐式转换成64位整数。但是,VC的输入输出与__int64的兼容就不是很好了,如果你写下这样一段代码:

注意:__int64是两个短的下划线

#include<bits/stdc++.h>

using namespace std;

#define ll long long

ll kata[36];

int main()

{

    int n;kata[0]=1;

    kata[1]=1;//

    for(int i=2;i<=35;i++)

    {

        ll sum=0;

        for(int j=0;j<i;j++)

        {

            sum+=kata[j]*kata[i-j-1];

 

        }

        kata[i]=sum;

    }

    int flag=1;

    while(cin>>n)

    {

        if(n==-1)

        {

            break;

        }

        cout<<flag<<" "<<n<<" "<<kata[n]*2<<endl;//

        flag++;

 

    }

    return 0;

}

 

Hdu 5184

题意:给出一个数字 n ,然后会有 n '(' ')' 组成一个字符串序列,这个字符串序列的 ( ) 是相互匹配的,现在给出这个字符串序列的前几项,要你判断符合前缀为给出序列的字符串会有多少种??

题解:如果没有前缀条件就是裸的卡特兰数的模型.如果已经确定了前缀,当前缀满足的情况下,对于后面的串这个时候 '(' 的数量不会会大于等于 ')' 的数量,所以我们将其看成一个经典的买票模型.

n+m个人排队买票,并且满足,票价为50元,其中n个人各手持一张50元钞票,m个人各手持一张100元钞票,除此之外大家身上没有任何其他的钱币,并且初始时候售票窗口没有钱,问有多少种排队的情况数能够让大家都买到票。

这里的话将 ')' 看成50 的,'(' 看成100的,只要当前的 ')'比 '(' 多我们总是可以找到一个序列.所以这里还是一个卡特兰数模型。

问题大意是用S表示入栈,X表示出栈,那么合法的序列有多少个(S的个数为n)显然有c(2n, n)个含S,X各n个的序列,剩下的是计算不允许的序列数(它包含正确个数的S和X,但是违背其它条件).在任何不允许的序列中,定出使得X的个数超过S的个数的第一个X的位置。然后在导致幷包括这个X的部分序列中,以S代替所有的X并以X代表所有的S。结果是一个有(n+1)个S和(n-1)个X的序列。反过来,对一垢一种类型的每个序列,我们都能逆转这个过程,而且找出导致它的前一种类型的不允许序列。例如XXSXSSSXXSSS必然来自SSXSXXXXXSSS。这个对应说明,不允许的序列的个数是c(2n, n-1),因此an = c(2n, n) - c(2n,

 n-1)。

 

这个解法正好能适用于一种特殊情况,以下是对其的叙述:

n+m个人排队买票,并且满足,票价为50元,其中n个人各手持一张50元钞票,m个人各手持一张100元钞票,除此之外大家身上没有任何其他的钱币,并且初始时候售票窗口没有钱,问有多少种排队的情况数能够让大家都买到票。

 

这个题目是Catalan数的变形,不考虑人与人的差异,如果m=n的话那么就是我们初始的Catalan数问题,也就是将手持50元的人看成是+1,手持100元的人看成是-1,任前k个数值的和都非负的序列数。

 

这个题目区别就在于n>m的情况,此时我们仍然可以用原先的证明方法考虑,假设我们要的情况数是,无法让每个人都买到的情况数是,那么就有,此时我们求,我们假设最早买不到票的人编号是k,他手持的是100元并且售票处没有钱,那么将前k个人的钱从50元变成100元,从100元变成50元,这时候就有n+1个人手持50元,m-1个手持100元的,所以就得到,于是我们的结果就因此得到了,表达式是。

(出处:http://daybreakcx.is-programmer.com/posts/17315.html 作者daybreakcx)

根据费马小定理,我们可得出当p是素数时,对任意x,都有x^(p)≡  x(modp),

 

x无法被p整除,那么x^(p-1)≡  1(modp),

那么可得出当模数p为素数x^(p-2)就是x的逆元。

要注意逆元

Output Limit Exceeded 多数发生在递归遍历的过程中,多输出了一些内容(比如说空格)。Output Limit Exceeded还指如果输入某一组数据,你的程序返回的结果是一直输出某个结果,死循环输出的那种。

#include<bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn=1e6+5;

ll f[maxn];

int n;

const ll modn=1e9+7;

void init()

{

    f[0]=f[1]=1;

    for(int i=2;i<maxn;i++)

    {

        f[i]=(f[i-1]*i)%modn;//mod

    }

    return ;

}

ll fastpow(ll a,ll n)

{

    ll res=1;

    while(n)

    {

        if(n&1)

        {

            res*=a;

            res%=modn;

        }

        a*=a;

        a%=modn;

        n>>=1;

 

    }

    return res;

}

ll c(ll n,ll m)

{

    ll res=f[m]*f[n-m]%modn;

    res=fastpow(res,modn-2);//求逆元

    return f[n]*res%modn;

 

}

char s[maxn];

int main()

{

    ios::sync_with_stdio(false);

    init();

    while(scanf("%d",&n)!=EOF)//

    {

        getchar();//字符串输入要小心

        scanf("%s",s);//

 

        int len=strlen(s);

        if(n%2==1)

        {

            cout<<0<<endl;

            continue;

        }

        int l=0;int r=0;int flag=0;

        for(int i=0;i<len;i++)

        {

            if(s[i]=='(') l++;

            else r++;

            if(l<r)

            {

                flag=1;

                break;

 

            }

 

        }

        if(flag||l<r)

        {

            cout<<0<<endl;

            continue;

        }

 

        l=n/2-l; r=n/2-r;

        if(l<0||r<0)

        {

            cout<<0<<endl;

            continue;

        }

        cout<<(c(l+r,r)-c(l+r,r+1)+modn)%modn<<endl;//c

 

      //  cout<<"e"<<endl;

 

 

    }

    return 0;

 

}

 

Hdu 1023

卡特兰数模板题,可以自己写一遍吧

不,是个大数卡特兰数

#include<bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn=1e2+10;

int a[maxn][maxn];

int b[maxn];

void pre()

{

    //a[0][0]=1;

    a[1][0]=1;b[1]=1;

   // cout<<b[1]<<endl;

    int len=1;//注意回自己进位

    for(int i=2;i<=100;i++)//注意不能超出范围,如果超出就会出现奇怪的东西

    {

 

        for(int j=0;j<len;j++)//

        {

            a[i][j]=a[i-1][j]*(4*i-2);

 

        }

        int carry=0;

        for(int j=0;j<len;j++)

        {

            int temp=(a[i][j]+carry);

            a[i][j]=temp%10;

            carry=temp/10;

        }

        while(carry)

        {

            a[i][len++]=carry%10;

            carry/=10;

        }

        for(int j=len-1;j>=0;j--)

        {

            int temp=carry*10+a[i][j];

            a[i][j]=temp/(i+1);

            carry=temp%(i+1);

        }

        while(!a[i][len-1])

        {

            len--;

        }

        b[i]=len;

      // cout<<i<<" "<<len<<endl;

      // cout<<b[i]<<endl;

        //

    }

    return ;

 

}

int main()

{

    int n;

    pre();

      //  cout<<b[1]<<endl;

    while(scanf("%d",&n)!=EOF)

 

    {

//cout<<b[1]<<endl;

    //    cout<<b[2]<<endl;

        for(int i=b[n]-1;i>=0;i--)

        {

            cout<<a[n][i];

        }

        cout<<endl;

 

 

    }

    return 0;

 

}

 

Hdu 1130

#include<bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn=1e2+10;

int a[maxn][maxn];

int b[maxn];

void pre()

{

    //a[0][0]=1;

    a[1][0]=1;b[1]=1;

   // cout<<b[1]<<endl;

    int len=1;//注意回自己进位

    for(int i=2;i<=100;i++)//注意不能超出范围,如果超出就会出现奇怪的东西,要注意100就要用大数了,可能非常大

    {

 

        for(int j=0;j<len;j++)//

        {

            a[i][j]=a[i-1][j]*(4*i-2);

 

        }

        int carry=0;

        for(int j=0;j<len;j++)

        {

            int temp=(a[i][j]+carry);

            a[i][j]=temp%10;

            carry=temp/10;

        }

        while(carry)

        {

            a[i][len++]=carry%10;

            carry/=10;

        }

        for(int j=len-1;j>=0;j--)

        {

            int temp=carry*10+a[i][j];

            a[i][j]=temp/(i+1);

            carry=temp%(i+1);

        }

        while(!a[i][len-1])

        {

            len--;

        }

        b[i]=len;

      // cout<<i<<" "<<len<<endl;

      // cout<<b[i]<<endl;

        //

    }

    return ;

 

}

int main()

{

    int n;

    pre();

      //  cout<<b[1]<<endl;

    while(scanf("%d",&n)!=EOF)

 

    {

//cout<<b[1]<<endl;

    //    cout<<b[2]<<endl;

        for(int i=b[n]-1;i>=0;i--)

        {

            cout<<a[n][i];

        }

        cout<<endl;

 

 

    }

    return 0;

 

}

与上面那道题一样。

Hdu 3240

#include<bits/stdc++.h>

using namespace std;

#define ll long long

const ll maxn=30000;

ll prime[maxn];

ll num[maxn];

int np;

void exgcd(ll a,ll b,ll &x,ll&y )

{

    if(b==0)

    {

        x=1;

        y=0;

        return ;

    }

    exgcd(b,a%b,x,y);

    ll temp=x;

    x=y;

    y=temp-a/b*y;

}

 

void calc(ll &ans,ll tp,ll&m) //为了快点传&

{

    //cout<<tp<<"h"<<endl;

    for(int i=0;i<np&&prime[i]<=tp;i++)

    {

      //  cout<<prime[i]<<"sh"<<endl;

        if(tp%prime[i]==0)

        {

            while(tp%prime[i]==0)

            {

                num[i]++;

                tp/=prime[i];

          //  cout<<tp<<"tp"<<endl;

            }

        }

    }

    ans=(ans*tp)%m;

//cout<<"cal"<<ans<<endl;

}

//ll x,y;

void cal(ll &ans,ll tp,ll &m)

{

   // cout<<tp<<" "<<ans<<endl;

 

    ll x,y;

    for(int i=0;i<np&&prime[i]<=tp;i++)

    {

        if(tp%prime[i]==0)

        {

            while(tp%prime[i]==0)

            {

                num[i]--;//zhuyi xiabiao

                tp/=prime[i];

        //        cout<<tp<<"tp"<<endl;

            }

        }

    }

    exgcd(tp,m,x,y);

  //  cout<<x<<"x"<<endl;

    //ans*=(x+m)%m;

   // ans%=m;

   ans=(ans*((x%m+m)%m))%m;

 //  cout<<"cal2"<<ans<<endl;

}

int main()

{

    ll n,m ;

    while(scanf("%lld%lld",&n,&m)!=EOF,n||m)//

    {

        ll ans=1;ll temp=1;//fangzhi gaibian ans

        ll res=1;np=0;

        ll q=m; //cout<<q<<endl;

        for(int i=2;i*i<=q;i++)

        {

            if(q%i==0)

            {

                prime[np++]=i;

           //     cout<<i<<"prim"<<endl;

                while(q%i==0)

                {

                    q/=i;

                }

            }

        }

        if(q>1) prime[np++]=q;//tiaojian nongcuole

        memset(num,0,sizeof(num));

        for(int i=2;i<=n;i++)

        {

            calc(ans,4*i-2,m);

            cal(ans,i+1,m);

            temp=ans;

           // cout<<ans<<"ans"<<endl;

            for(int j=0;j<np;j++)

            {

                if(num[j])

                for(int k=0;k<num[j];k++)

                {

                    temp=(temp*prime[j])%m;

                }

            }

            res=(res+temp)%m;

         //   cout<<res<<endl;

        }

       // for

        cout<<res<<endl;

    }

    return 0;

}

尽量一遍 写对,也就是要清楚。分解质因数

Hdu 4828

首先缩小范围,1是一定最先进去的,6是最后出去的,观察数据可知,中间确定前面的后也有一定的关系,从而拓扑排序或者卡特兰数的栈。又从答案看,可推测是卡特兰数。然后是从小到大之间有关系,所以从小到大放,而且右边的大于左边,下面大于上面,所以,既可以放右边或者下面,然而下面放好之后,只能放右边,相当于栈的出栈后只能进栈。同时有两种可能操作,就是放下面的出栈和放右边的入栈。

首先求逆元的话,可用费马小定理,也可以用扩展欧几里得

#include<bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn=1e6+10;

const int modn=1e9+7;

ll c[maxn];

ll quickmow(ll a,ll b)

{

    ll res=1;

    while(b)

    {

        if(b&1)

        {

            res=(res*a)%modn;

        }

        a=(a*a)%modn;

        b>>=1;

    }

    return res;

}

void exgcd(ll a,ll b,ll &x,ll &y)

{

    if(b==0)

    {

        x=1;

        y=0;return ;

    }

    exgcd(b,a%b,x,y);//

    ll tmp=x;

    //y=x;

    x=y;

 

    y=tmp-(a/b)*y;//

 

}

ll cal(ll a,ll n)

{

    ll x,y;

    exgcd(a,n,x,y);

    return (x%n+n)%n;//x可能是负数

}

void pre()

{

    c[1]=1;c[2]=1;

    for(int i=2;i<=maxn;i++)

    {

        c[i]=(c[i-1]*(4*i-6))%modn*cal(i,modn)%modn;//jicuo gongshile

        //c[i]=

    }

 

}

int main()

{

    int t;

    //cin>>t;

    c[1]=1;c[2]=1;

    //cout<<c[2]<<endl;

    for(int i=3;i<=maxn;i++)

    {

        //cout<<cal(i,modn)<<endl;

 

        c[i]=(c[i-1]*(4*i-6))%modn*cal(i,modn)%modn;//jicuo gongshile

        //cout<<c[i]<<endl;

        //c[i]=

    }

    cin>>t;int ccase=0;

 

  //  pre();

    while(t--)

    {

        ll n;

        cin>>n;

        cout<<"Case #"<<++ccase<<":"<<endl;

        cout<<c[n+1]<<endl;

    }

    return 0;

 

}

注意格式

Hdu 5673

Hdu 5177

Poj 2096

Hdu 4035dp 求期望

Hdu 3853

Hdu 4405

Poj 3071

Poj 3744

Hdu 4089

Hdu 1846

#include<bits/stdc++.h>

using namespace std;

int sg[1101];

int s[1101];

int n,m;

void getsg()

{

    memset(sg,0,sizeof(sg));

    for(int i=1;i<=n;i++)

    {

        memset(s,0,sizeof(s));

        for(int j=1;j<=m&&i-j>=0;j++)

        {

            s[sg[i-j]]=1;

        }

        for(int j=0;j<=n;j++)

        {

            if(!s[j])

            {

                sg[i]=j;

                break;

            }

        }

    }

    return ;

}

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

        cin>>n>>m;

        getsg();

        if(!sg[n]) cout<<"second"<<endl;

        else cout<<"first"<<endl;

 

    }

    return 0;

}

可以用SG函数。特殊的。

Hdu 1850

Hdu 1907

Hdu 2999

Hdu 1524

//Hdu 4111

Hdu 4111

Hdu 4203

Hdu 1527

威佐夫游戏,是个规律啊,要写出来小规模的似乎也比较难。

#include<bits/stdc++.h>

using namespace std;

int main()

{

    int n,m;double shu=(1+sqrt(5))/2;//

    while(cin>>n>>m)

    {

        int a=min(n, m);

        int b=max(n,m);

        int res=(int)((b-a)*1.0*shu);

        if(a==res) cout<<0<<endl;

        else cout<<1<<endl;

    }

    return 0;

}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章