筆記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;

}

 

 

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