博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

NOIP的模板--考前复习

距离NOIP还有-1天

可以去放弃一些巨难得题目去搞一些模板了

              -------在校老师的原话

一·快排

虽然可以手打,最好用STL,里面有很多优化,会快很多

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 struct node
 5 {
 6     int x,y;
 7 }a[maxn];
 8 bool cmp(node a,node b)
 9 {
10     return a.x<b.x;
11 }
12 int main()
13 {
14     sort(a+1,a+1+n,cmp);
15     return 0;
16  } 
View Code

二·冰茶姬

一个很好用,很好压行的神奇初级(虽然难题是真的不会)黑科技。

1  int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
View Code

三·快速幂||取模运算(就是快速幂里要取模)

 1 int KSM(int a,int b,int c)
 2 {
 3     int ans=1;a%=c;
 4     while(b>0)
 5     {
 6         if(b%2==1)ans=ans*a%c;
 7         b/=2;a=a*a%c;
 8     }
 9     return ans;    
10 }
View Code

四·线性筛素数

这题有很多方法,比如瞎搞,因为大于10的素数一定都在6的倍数的两边,至于证明什么的可以去找数竞。

或者可以用埃筛(几乎是线性),或者用欧筛

  • 以6的倍数来搞事的判断方法:
  • 1 bool prime(int n)
    2 {
    3     if(n==1)return false;
    4     if(n==2||n==3)return true;
    5     if(n%6!=1&&n%6!=5)return false;
    6     for(int i=5;i*i<=n;i+=6)
    7     if(n%i==0||n%(i+2)==0)retrun false;
    8     return true;
    9 }
    View Code

    埃筛

  • 1 void make_prime()
    2 {
    3     memset(prime,true,sizeof(prime));
    4     prime[0]=prime[1]=false;
    5     int t=sqrt(MAXN);
    6     for(register int i=2;i<=t;i++)if(prime[i])
    7     for(register int j=2*i;j<MAXN,j+=i)
    8     prime[j]=false;
    9 }
    View Code

    欧筛

  •  1 void make_prime()
     2 {
     3     memset(prime,true,sizeof(prime));
     4     prime[0] = prime[1] = false;
     5     for( int i = 2; i <= MAXN; i++) {
     6         if( prime[i] ) Prime[ num ++ ] = i;
     7         for(int j = 0;j<num && i*Prime[j] < MAXN; j++) {
     8             prime[ i*Prime[j] ] = false;
     9             if( !( i%Prime[j] ) ) break;
    10         }
    11     }
    12     return;
    13 }
    View Code

    还有一些其他搞事的办法,但埃筛,一般就够用了

五·最小生成树

人生信条能打kruskal永远不打prim!!!!!!

 1 void kruskal()
 2 {
 3     int f1,f2,k,i;
 4     k=0;
 5     for(i=1;i<=n;i++)
 6     prt[i]=i;
 7     for(i=1;i<=m;i++)
 8     {
 9         f1=find(a[i].x);
10         f2=find(a[i].y);
11         if(f1!=f2)
12         {
13             ans=ans+a[i].z;
14             prt[f1]=f2;
15             k++;
16             if(k==n-1)
17             break;
18         }
19     }
20     if(k<n-1)
21     {
22         cout<<"orz"<<endl;
23         bj=0;
24         return ;
25     }
26 }
View Code

六·单源最短路弱化版(SPFA)

能打SPFA不打dijkstra!!!!!!!!

 1 inline void spfa(int k)
 2 {
 3     queue< int >q;
 4     dis[k] = 0; q.push(k); vis[k] = 0;
 5     while(!q.empty()) {
 6         x = q.front(); q.pop(); vis[x] = 0;
 7         for(int i = head[x]; i != 0; i = way[i].next ) {
 8             if(dis[x] + way[i].w < dis[way[i].to]) {
 9                 dis[way[i].to] = dis[x] + way[i].w;
10                 if(vis[way[i].to] == 0) {
11                     q.push(way[i].to);
12                     vis[way[i].to] = 1;
13                 }
14             }
15         }
16     }
17 }
View Code

七·树状数组

 1 int lowbit(int x)
 2 {
 3     return x&(-x);
 4 }
 5 int add(int x,int y)
 6 {
 7     while(x<=n)
 8     {
 9         c[x]+=y;
10         x+=lowbit(x);
11     }
12 }
13 int sum(int x)
14 {
15     int res=0;
16     while(x>0)
17     {
18         res+=c[x];
19         x-=lowbit(x);
20     }
21     return res;
22 }
View Code

八·乘法逆元

线性的,还有什么费马小,感觉没什么用,就没打

 1 int CFNY(int n)
 2 {
 3     inv[1]=1;
 4     cout<<1<<endl;
 5     for(int i=2;i<=n;i++)
 6     {
 7         inv[i]=(long long )(p-p/i)*inv[p%i]%p;
 8         cout<<inv[i]<<endl;
 9     }
10 }
View Code

九·康托展开

绝对没人会在NOIP考这个东西,要是他考了,以后就可以说 这很NOIP。。。。

 

 1 ll kangtuo(ll x[])
 2 {
 3     ll p=0;
 4     for(ll i=1;i<=n;i++)
 5     {
 6         ll t=0;
 7         for(ll j=i+1;j<=n;j++)
 8         {
 9             if(x[i]>x[j])
10             {
11                 t++;
12             }
13         }
14         p+=t*fc[n-i];
15     }
16     return p+1;
17 }
View Code

十·最近公共祖先(LCA)

 1 void dfs(int x,int father)//x为当前节点,father为其父节点 
 2 {
 3     deep[x]=deep[father]+1;//当前点的深度为其父节点深度加1 
 4     parents[x][0]=father;//当前点的2^0祖先(也就是上1级祖先)就是其父节点 
 5     for(int i=1;(1<<i)<=deep[x];i++)
 6     {
 7         parents[x][i]=parents[parents[x][i-1]][i-1];
 8         //这里应该是整个预处理阶段中最有灵魂的部分了
 9         //x的2^i级祖先就是x的2^(i-1)级祖先的2^(i-1)级的祖先 。
10         //2^i==2^(i-1)+2^(i-1),这个式子好像没什么可说的 
11     }
12     for(int i=head[x];i;i=way[i].next)
13     {
14         int to=way[i].to;
15         if(to!=father)
16         dfs(to,x);
17      } 
18  } 
19  
20 int lca(int a,int b)//a,b为两个要查询的点 
21 {
22     if(deep[a]>deep[b])//我时刻保证a的深度比b的小 
23     {
24         swap(a,b); //如果反了就换一下 
25     }
26     for(int i=20;i>=0;i--)
27     {
28          if(deep[a]<=deep[b]-(1<<i)) 
29          b=parents[b][i];//将a和b跳的同一高度 
30     } 
31     if(a==b)//如果b在跳上来时和a一样了,那说明a就是a和b的LCA,直接返回就行了 
32     return a;
33     for(int i=20;i>=0;i--)
34     {
35         if(parents[a][i]==parents[b][i])
36         continue;
37         else
38         {
39             a=parents[a][i];
40             b=parents[b][i];//将a和b一起往上跳 
41         }
42     }
43     return parents[a][0];//找出最后的答案 
44 }
View Code

十一·卢卡斯

只存在于组合数里的东西

 1 long long CC(long long n,long long m){
 2     if(m>n)
 3     return 0;
 4     return ((c[n]*KSM(c[m],p-2,p))%p*KSM(c[n-m],p-2,p)%p);
 5 }
 6 long long  Lucas(long long n,long long m){
 7     if(!m)
 8     return 1;
 9     return CC(n%p,m%p)*Lucas(n/p,m/p)%p;
10 }
View Code

十二·二分图匹配

 1 int dfs(int t)
 2 {
 3     for (int i=1; i<=n2; ++i)
 4         if (a[t][i] == 1 && check[i] == 0)
 5         {
 6             check[i] = 1;
 7             if (p[i] == 0 || dfs(p[i]) == 1)
 8             {
 9                 p[i] = t;
10                 return 1;
11             }
12         }
13     return 0;
14 }
View Code

十三·强连通分量(tarjan)

 1 void tarjan(int s)
 2 {
 3     dfn[s]=low[s]=++tim;
 4     in[s]=1,stack[++top]=s;
 5     for(int i=head[s];i;i=edge[i].next)
 6     {
 7         int v=edge[i].to;
 8         if(!dfn[v])
 9         {
10             tarjan(v);
11             low[s]=min(low[v],low[s]);
12         }
13         else if(in[v]&&low[s]>dfn[v])low[s]=dfn[v];
14     }
15     if(dfn[s]==low[s])
16     {
17         int p;
18         belong[s]=++cnt;
19         do
20         {
21             p=stack[top--];
22             in[p]=0;
23             belong[p]=cnt;
24         }while(p!=s);
25     }
26 }
View Code

 十四·割点(还是那个有名的tarjan)

 1 int tarjan(int x,int y)
 2 {
 3     low[x]=dfn[x]=++tim;
 4     int child=0;
 5     for(int i=head[x];i;i=way[i].next)
 6     {
 7         int v=way[i].to ;
 8         if(!dfn[v])
 9         {
10             tarjan(v,y);
11             low[x]=min(low[x],low[v]);
12             if(dfn[x]<=low[v]&&x!=y)
13             {
14                 cut[x]=1;
15             }
16             if(x==y)
17             {
18                 child++;
19             }
20         }
21         low[x]=min(low[x],dfn[v]);
22         if(child>=2&&x==y)
23         {
24             cut[x]=1;
25         }
26     }
27 }
View Code

 

 十五·对拍之造数据(maker)Windows下

eg. 2个正整数x0,y0

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     freopen("data.in","w",stdout);
 6     srand(time(NULL));
 7     int n=rand();
 8     int m=rand();//可以在这里加模数来控制范围 
 9     cout<<n<<" "<<m<<endl;
10 }
View Code

 

 十六·对拍之检查(check)Windows下

这个在用之前一定要先把所有的程序先跑一下,然后一定要在同一各根目录下,不然有可能会用一些很神奇的东西把源程序给覆盖掉

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     while(1)
 6     {
 7         system("maker");
 8         system("true");
 9         system("false");
10         if(system("fc false.out true.out")
11         {
12             cout<<"WA"<<endl;
13             break;
14         }
15         cout<<"AC"<<endl;
16     }
17     return 0;
18  } 
View Code

 十七·缩点(还是那个tarjan)

 1 void tarjan(int x)
 2 {
 3     low[x]=dfn[x]=++tim;
 4     stac[++top]=x;
 5     vis[x]=1;
 6     for(int i=head[x];i;i=edge[i].next)
 7     {
 8         int v=edge[i].to;
 9         if(!dfn[v])
10         {
11             tarjan(v);
12             low[x]=min(low[x],low[v]);
13         }
14         else if(vis[v])
15         {
16             low[x]=min(low[x],dfn[v]);
17         }
18     }
19     if(dfn[x]==low[x])
20     {
21         int y;
22         while(y=stac[top--])
23         {
24             sd[y]=x;
25             vis[y]=0;
26             if(x==y)
27             break;
28             p[x]+=p[y];
29         }
30     }
31 }
View Code

 

 十八·网络最大流(很NOIP的一个东西)

 1 int bfs()
 2 {
 3     memset(deep,0x3f,sizeof(deep));
 4     memset(in,0,sizeof(in));
 5     deep[s]=0;
 6     queue<int >q;
 7     q.push(s);
 8     while(!q.empty())
 9     {
10         int x=q.front();
11         q.pop();
12         in[x]=0;
13         for(int i=head[x];i;i=way[i].next)
14         {
15             int v=way[i].to;
16             if(deep[v]>deep[x]+1&&way[i].value)
17             {
18                 deep[v]=deep[x]+1;
19                 if(in[v]==0)
20                 {
21                     q.push(v);
22                     in[v]=1;
23                 }
24             }
25         }
26     }
27     if(deep[t]!=0x3f3f3f3f)
28     return 1;
29     return 0;
30 }
31 int dfs(int x,int y)
32 {
33     ans=0;
34     if(x==t)
35     return y;
36     for(int i=head[x];i;i=way[i].next)
37     {
38         int v=way[i].to;
39         if(way[i].value&&deep[v]==deep[x]+1)
40         {
41             if(ans=dfs(v,min(y,way[i].value)))
42             {
43                 way[i].value-=ans;
44                 way[i^1].value+=ans;
45                 return ans;
46             }
47         }
48     }
49     return 0;
50 }
51 int dinic()
52 {
53     low=0;
54     while(bfs())
55     {
56         while(low=dfs(s,inf))
57         maxnn+=low;
58     }
59     return maxnn;
60 }
View Code

 

十九·最小费用最大流

 1 int spfa()
 2 {
 3     memset(dis,0x3f,sizeof(dis));
 4     memset(pre,0,sizeof(pre));
 5     memset(in,0,sizeof(in));
 6     queue<int >q;
 7     q.push(s);
 8     in[s]=1;
 9     dis[s]=0;
10     while(!q.empty())
11     {
12         int x=q.front();
13         q.pop();
14         in[x]=0;
15         for(int i=head[x];i;i=way[i].next)
16         {
17             int v=way[i].to;
18             int w=way[i].cost;
19             if(way[i].value>0&&dis[v]>dis[x]+w)
20             {
21                 dis[v]=dis[x]+w;
22                 pre[v].from=x;
23                 pre[v].edge=i;
24                 if(in[v]==0)
25                 {
26                     q.push(v);
27                     in[v]=1;
28                 }
29             }
30         }
31     }
32     return dis[t]!=0x3f3f3f3f;
33 }
34 int ek()
35 {
36     ans=0;
37     cost=0;
38     int mi;
39     int i;
40     while(spfa())
41     {
42         mi=inf;
43         for(i=t;i!=s;i=pre[i].from)
44         {
45             mi=min(mi,way[pre[i].edge].value);
46         }
47         for(i=t;i!=s;i=pre[i].from)
48         {
49             way[pre[i].edge].value-=mi;
50             way[pre[i].edge^1].value+=mi;
51         }
52         ans+=mi;
53         cost+=mi*dis[t];
54     }    
55     return ans;
56 }
View Code

 

二十·高精度加减乘除模

 

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 struct Big
  4 {
  5     static const int BASE = 100000000;
  6     static const int WIDTH = 8;
  7     vector<long long> s;
  8     Big()
  9     {
 10         *this = 0;
 11     }
 12     Big(const int &num)
 13     {
 14         *this = num;
 15     }
 16 
 17     Big operator=(int num)
 18     {
 19         s.clear();
 20         do
 21         {
 22             s.push_back(num % BASE);
 23             num /= BASE;
 24         } while (num > 0);
 25         return *this;
 26     }
 27     Big operator=(const string &str)
 28     {
 29         s.clear();
 30         int x, len = (str.length() - 1) / WIDTH + 1;
 31         for (int i = 0; i < len; i++)
 32         {
 33             int end = str.length() - i * WIDTH;
 34             int start = max(0, end - WIDTH);
 35             sscanf(str.substr(start, end - start).c_str(), "%lld", &x);
 36             s.push_back(x);
 37         }
 38         return *this;
 39     }
 40     bool operator<(const Big &b)
 41     {
 42         if (s.size() < b.s.size())
 43             return true;
 44         if (s.size() > b.s.size())
 45             return false;
 46         for (int i = s.size() - 1; i >= 0; i--)
 47         {
 48             if (s[i] < b.s[i])
 49                 return true;
 50             if (s[i] > b.s[i])
 51                 return false;
 52         }
 53         return false;
 54     }
 55     bool operator>=(const Big &b)
 56     {
 57         return !(*this < b);
 58     }
 59     bool operator==(const Big &b)
 60     {
 61         if (s.size() != b.s.size())
 62             return false;
 63         for (int i = 0; i < s.size(); i++)
 64             if (s[i] != b.s[i])
 65                 return false;
 66         return true;
 67     }
 68     Big operator+(const Big &b)
 69     {
 70         Big c;
 71         c.s.clear();
 72         for (int i = 0, g = 0;; i++)
 73         {
 74             if (g == 0 && i >= s.size() && i >= b.s.size())
 75                 break;
 76             int x = g;
 77             if (i < s.size())
 78                 x += s[i];
 79             if (i < b.s.size())
 80                 x += b.s[i];
 81             c.s.push_back(x % BASE);
 82             g = x / BASE;
 83         }
 84         return c;
 85     }
 86     Big operator-(const Big &b)
 87     {
 88         Big c;
 89         c = *this;
 90         for (int i = 0; i < c.s.size(); i++)
 91         {
 92             int tmp;
 93             if (i >= b.s.size())
 94                 tmp = 0;
 95             else
 96                 tmp = b.s[i];
 97             if (c.s[i] < tmp)
 98             {
 99                 c.s[i + 1] -= 1;
100                 c.s[i] += BASE;
101             }
102             c.s[i] -= tmp;
103         }
104         while (c.s.back() == 0 && c.s.size() > 1)
105             c.s.pop_back();
106         return c;
107     }
108     void operator-=(const Big &b)
109     {
110         *this = *this - b;
111     }
112     Big operator*(const Big &b)
113     {
114         Big c;
115         c.s.resize(s.size() + b.s.size());
116         for (int i = 0; i < s.size(); i++)
117             for (int j = 0; j < b.s.size(); j++)
118                 c.s[i + j] += s[i] * b.s[j];
119         for (int i = 0; i < c.s.size() - 1; i++)
120         {
121             c.s[i + 1] += c.s[i] / BASE;
122             c.s[i] %= BASE;
123         }
124         while (c.s.back() == 0 && c.s.size() > 1)
125             c.s.pop_back();
126         return c;
127     }
128     friend istream &operator>>(istream &input, Big &x)
129     {
130         string s;
131         if (!(input >> s))
132             return input;
133         x = s;
134         return input;
135     }
136     friend ostream &operator<<(ostream &output, const Big &x)
137     {
138         output << x.s.back();
139         for (int i = x.s.size() - 2; i >= 0; i--)
140         {
141             char buf[20];
142             sprintf(buf, "%08d", x.s[i]);
143             for (int j = 0; j < strlen(buf); j++)
144                 output << buf[j];
145         }
146         return output;
147     }
148 };
149 Big Copy(const Big &b, int x)
150 {
151     Big t;
152     t.s.resize(b.s.size() + x);
153     for (int i = 0; i < b.s.size(); i++)
154         t.s[i + x] = b.s[i];
155     return t;
156 }
157 Big Divide(const Big &a, const Big &b, Big &mod)
158 {
159     Big c;
160     c.s.resize(a.s.size() - b.s.size() + 1);
161     mod = a;
162     int Pow[(int)log2(Big::BASE) + 5];
163     Pow[0] = 1;
164     for (int i = 1; i <= log2(Big::BASE); i++)
165         Pow[i] = Pow[i - 1] * 2;
166     for (int i = c.s.size() - 1; i >= 0; i--)
167     {
168         Big t;
169         t = Copy(b, i);
170         for (int j = log2(Big::BASE); j >= 0; j--)
171             if (mod >= t * Pow[j])
172             {
173                 c.s[i] += Pow[j];
174                 mod -= t * Pow[j];
175             }
176     }
177     while (c.s.back() == 0 && c.s.size() > 1)
178         c.s.pop_back();
179     return c;
180 }
181 Big a, b;
182 int main()
183 {
184     cin >> a >> b;
185     if (a < b)
186         cout << a + b << endl << '-' << b - a << endl<< a * b << endl << 0 << endl << a << endl;
187     else
188     {
189         Big c, d;
190         c = Divide(a, b, d);
191         cout << a + b << endl << a - b << endl << a * b << endl << c << endl << d << endl;
192     }
193     return 0;
194 }
高精度

 

 

 

 二十一. 最大公约数和最小公倍数

1 int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
2 int lcm(int a,int b)
3 {
4     a * b / gcd(a, b);
5 }
View Code

 二十二.简单乘法(防止因为乘数过大而爆long long)和快速幂

 1 int muti(int a,int b)//乘法,防止乘数太大爆long long 
 2 {
 3     int ans=0;
 4     while(b)
 5     {
 6         if(b&1)
 7         {
 8             ans=(ans+a)%mod;
 9         }
10         a=(a+a)%mod;
11         b>>=1;
12     }
13     return ans;
14 }
15 int KSM(int a,int b)//快速幂 
16 {
17     int ans=1;
18     while(b)
19     {
20         if(b&1)
21         {
22             ans=nuti(ans,a);
23         }
24         a=muti(a,a);
25         b>>=1;
26     }
27     return ans;
28 }
View Code

二十三.质因数分解

 1 int devide(int x)//质因数分解 
 2 {
 3     for(int i=1;i<=sum&&prime[i]*prime[i]<=x;++i)
 4     {
 5         while(x%prime[i]==0)
 6         {
 7             x/=prime[i];
 8             cout<<prime[i]<<" ";
 9         }
10     }
11     if(x!=1)
12     {
13         cout<<x<<" ";
14     }
15     
16 }
View Code

二十四.拓展欧里几德

 1 void exgcd(int a,int b,int &x,int &y)//拓展欧里几德 
 2 {
 3     if(!b)
 4     {
 5         x=1;
 6         y=0;
 7         return ;
 8     }
 9     exgcd(b,a%b,y,x);
10     y-=a/b*x;
11 } 
View Code

 

二十五.逆元的几种求法

  • 快速幂版

 1 inv=KSM(x,Mod-2);//逆元 (快速幂版) 

  • 拓展欧里几德版

 1 exgcd(x,Mod,inv,y); 2 inv=(inv+Mod)%Mod; //(x必须与mod互质) 

  • 线性求逆元,公式版
1 inv[1]=1;//线性公式 
2 for(i=2;i<=n;++i)
3     inv[i]=1ll*(Mod-Mod/i)*inv[Mod%i]%Mod; 

二十六.floyd

 1 int floyd()
 2 {
 3     for(int k=1;k<=n;k++)
 4     {
 5         for(int i=1;i<=n;i++)
 6         {
 7             for(int j=1;j<=n;j++)
 8             {
 9                 a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
10             }
11         }
12     }
13 }
View Code

二十七·最短路之几个瞎搞模板

 1 void spfa(int s)
 2 {
 3     int x, y, i;
 4     memset(dis, 0x3f, sizeof(dis));
 5     queue<int> q;
 6     q.push(s);
 7     dis[s] = 0;
 8     while (!q.empty())
 9     {
10         x = q.front();
11         q.pop();
12         vis[x] = false;
13         for (i = head[x]; i; i = way[i].next)
14         {
15             y = way[i].to;
16             if (dis[y] > dis[x] + way[i].value)
17             {
18                 dis[y] = dis[x] + way[i].value;
19                 if (!vis[y])
20                 {
21                     q.push(y);
22                     vis[y] = true;
23                 }
24             }
25         }
26     }
27 }
spfa
 1 priority_queue<pair<int, int>> q;
 2 void dijkstra(int s)
 3 {
 4     int x, y, i;
 5     memset(dis, 0x3f, sizeof(dis));
 6     q.push(make_pair(0, s));
 7     dis[s] = 0;
 8     while (!q.empty())
 9     {
10         x = q.top().second;
11         q.pop();
12         for (i = head[x]; i; i = way[i].next)
13         {
14             y = way[i].to;
15             if (dis[y] > dis[x] + way[i].value)
16             {
17                 dis[y] = dis[x] + way[i].value;
18                 q.push(make_pair(-dis[y], y));
19             }
20         }
21     }
22 }
dijkstra

 

二十八· 二分集合

 1 int l = 0;
 2     int r = maxx;
 3     while (l < r) 
 4     {
 5         int mid = (l + r) >> 1;
 6         if (check(mid))
 7         {
 8             r = mid;
 9         }
10         else
11         {
12             l = mid + 1;
13         }
14     }
二分最小值
 1 while (l < r)
 2     {
 3         int mid = (l + r) >> 1;
 4         if (check(mid))
 5         {
 6             l = mid;
 7         }
 8         else
 9         {
10             r = mid - 1;
11         }
12     }
二分最大值
 1 while (l + eps < r) 
 2     {
 3         double mid = (l + r) >> 1;
 4         if (check(mid))
 5         {
 6             r = mid;
 7         }
 8         else
 9         {
10             l = mid;
11         }
12     }
实数域二分

二十九· 树状数组求逆序对个数

1    for (int i = 1; i <= n; ++i)
2     {
3         cin >> x;
4         add(x, 1);
5         ans += i - sum(x);
6     }
树状数组求逆序对

三十·01背包

1 for (i = 1; i <= n; ++i)//背包 n为物品数,m为物品体积
2     {
3         cin >> v >> w;
4         for (j = m; j >= v; --j)
5             f[j] = max(f[j], f[j - v] + w);
6     }
7     cout << f[m] << endl;
01背包

 

三十一·完全背包

1  for (i = 1; i <= n; ++i)
2     {
3         cin >> v >> w; //背包 n为物品数,m为物品体积
4         for (j = v; j <= m; ++j)
5             f[j] = max(f[j], f[j - v] + w);
6     }
7     cout << f[m] << endl;
完全背包

 

三十二 ·最长上升子序列

1 d[k = 1] = a[1];//a是原序列,n为长度,k为最长上升子序列的长度
2     for (i = 2; i <= n; ++i)
3     {
4         if (d[k] < a[i])
5             d[++k] = a[i];
6         else
7             d[lower_bound(d + 1, d + k + 1, a[i]) - d] = a[i];
8     }
9     cout << k << endl;
最长上升子序列

 

三十三·最长公共子序列长度

 1 for (i = 1; i <= n; ++i)//串为a b,长度为n m
 2     {
 3         for (j = 1; j <= m; ++j)
 4         {
 5             if (A[i] == B[j])
 6                 f[i][j] = f[i - 1][j - 1] + 1;
 7             else
 8                 f[i][j] = max(f[i - 1][j], f[i][j - 1]);
 9         }
10     }
11     cout << f[n][m] << endl;
最长公共子序列

 

三十三·最长公共上升子序列

 1 B[0] = -inf;//一切概念均同上;
 2     for (i = 1; i <= n; ++i)
 3     {
 4         if (B[0] < A[i])
 5             num = f[i - 1][0];
 6         for (j = 1; j <= m; ++j)
 7         {
 8             if (A[i] == B[j])
 9                 f[i][j] = num + 1;
10             else
11                 f[i][j] = f[i - 1][j];
12             if (B[j] < A[i])
13                 num = max(num, f[i - 1][j]);
14         }
15     }
16     int ans = -inf;
17     for (i = 1; i <= m; ++i)
18         ans = max(ans, f[n][i]);
19     printf("%d", ans);
最长公共上升子序列

三十四· 倍增求LCA(必背,容易打错,一定要return)

 1 int pre() //LCA
 2 {
 3     for (int j = 1; j <= 18; j++)
 4     {
 5         for (int i = 1; i <= n; i++)
 6         {
 7             fa[i][j] = fa[fa[i][j - 1]][j - 1];
 8         }
 9     }
10 }
11 int lca(int x)
12 {
13     int i;
14     if (deep[x] < deep[y])
15     {
16         swap(x, y);
17     }
18     for (int i = 18; ~i; --i)
19     {
20         if (deep[fa[x][i]] >= deep[y])
21         {
22             x = fa[x][i];
23         }
24     }
25     if (x == y)
26     {
27         return x;
28     }
29     for (int i = 18; ~i; --i)
30     {
31         if (fa[x][i] != fa[y][i])
32         {
33             x = fa[x][i];
34             y = fa[y][i];
35         }
36     }
37     return fa[x][0];
38 }
LCA

 

三十五·树的直径(两次dfs就可以了)

 1 int dfs(int x) //树的直径 只要两次dfs就可以了。
 2 {
 3     int i, j;
 4     if (ans < d[x])
 5     {
 6         ans = d[x];
 7         p = x;
 8     }
 9     for (int i = head[x]; i; i = way[i].next)
10     {
11         j = v[i];
12         if (j != father)
13         {
14             d[j] = d[x] += w[i];
15             dfs(j, x);
16         }
17     }
18 }
19 void solve()
20 {
21     ans = 0;
22     d[1] = 0;
23     dfs(1, 0);
24     ans = 0;
25     d[p] = 0;
26     dfs(p, 0);
27     cout << ans << endl;
28 }
树的直径

 三十六·树的重心

 1 void dfs(int x, int father)//树的重心
 2 {
 3     int i, j;
 4     Max[x] = 0, size[x] = 1;
 5     for (i = head[x]; i; i = way[i].next)
 6     {
 7         j = way[i].to;
 8         if (j != father)
 9         {
10             dfs(j, x);
11             size[x] += size[j];
12             Max[x] = max(Max[x], size[j]);
13         }
14     }
15     Max[x] = max(Max[x], n - size[x]);
16     if (num > Max[x])
17     {
18         pos = x;
19         num = Max[x];
20     }
21 }
树的重心

 

 三十七·LCA树链剖分版,要稳定一些

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn = 5e5 + 10;
 6 
 7 int num, size[maxn], deep[maxn], fa[maxn], top[maxn], n, m, p, a, b;
 8 struct node
 9 {
10     int to;
11     int value;
12     int next;
13 }way[maxn<<1];
14 int tot = 0;
15 int head[maxn];
16 int add(int x,int y)
17 {
18     way[++tot].next = head[x];
19     way[tot].to = y;
20     head[x] = tot;
21 }
22 int dfs1(int x)
23 {
24     size[x] = 1;
25     deep[x] = deep[fa[x]] + 1;
26     for (int i = head[x]; i;i=way[i].next)
27     {
28         if(fa[x]!=way[i].to)
29         {
30             fa[way[i].to] = x;
31             dfs1(way[i].to);
32             size[x] += size[way[i].to];
33         }
34     }
35 }
36 int dfs2(int x)
37 {
38     int maxx = 0;
39     if(!top[x])
40     {
41         top[x] = x;
42     }
43     for (int i = head[x]; i;i=way[i].next)
44     {
45         if (fa[x] != way[i].to && size[way[i].to] > size[maxx])
46         {
47             maxx = way[i].to;
48         }
49     }
50     if(maxx)
51     {
52         top[maxx] = top[x];
53         dfs2(maxx);
54     }
55     for (int i = head[x]; i; i = way[i].next)
56     {
57         if(way[i].to!=maxx&&fa[x]!=way[i].to)
58         {
59             dfs2(way[i].to);
60         }
61     }
62 }
63 int lca(int x,int y)
64 {
65     while(top[x]!=top[y])
66     {
67         if(deep[top[x]]<deep[top[y]])
68         {
69             swap(x, y);
70         }
71         x = fa[top[x]];
72     }
73     if(deep[x]<deep[y])
74     {
75         return x;
76     }
77     return y;
78 }
79 int main()
80 {
81     ios::sync_with_stdio(false);
82     cin >> n >> m >> p;
83     for (int i = 1; i < n;i++)
84     {
85         cin >> a >> b;
86         add(a, b);
87         add(b, a);
88     }
89     dfs1(p);
90     dfs2(p);
91     for (int i = 1; i <= m;i++)
92     {
93         cin >> a >> b;
94         cout << lca(a, b) << endl;
95     }
96     return 0;
97 }
LCA

 三十八·字典树

  • 存树
1 struct node
2 {
3     int son[26];
4     int num;
5 } a[maxn];
View Code

 

  • 插入
 1 void Insert()
 2 {
 3     int l, i, p = 0;
 4     l = strlen(s);
 5     for (i = 0; i < l; ++i)
 6     {
 7         if (a[p].son[s[i] - 'a'] == 0)
 8             a[p].son[s[i] - 'a'] = ++t;
 9         p = a[p].son[s[i] - 'a'];
10         a[p].num++;
11 
12     }
13 }
View Code

 

  • 查询
 1 int find()
 2 {
 3     int l, i, p = 0;
 4     l = strlen(s);
 5     for (i = 0; i < l; ++i)
 6     {
 7         if (a[p].son[s[i] - 'a'] == 0)
 8             return 0;
 9         p = a[p].son[s[i] - 'a'];
10     }
11     return a[p].num;
12 }
View Code

三十九· 字符串hash

1 long long Hash()//base 是基数 ans 是hash值 l是长度 s[i]是第i个字符
2 {
3     long long  ans = 0;
4     for (int i = 0; i < l; ++i)
5         ans = ans * base + s[i];
6     return ans;
7 }
View Code

 四十·线段树1

 

 1 #include<iostream>
 2 using namespace std;
 3 const int maxn = 1e6 + 10;
 4 int a[maxn + 2];
 5 struct node
 6 {
 7     int l, r;
 8     long long pre, add;
 9 } tree[maxn];
10 
11 void build(int x,int l,int r)
12 {
13     tree[x].l = l;
14     tree[x].r = r;
15     if(l==r)
16     {
17         tree[x].pre = a[l];
18         return;
19     }
20     int mid = (l + r) >> 1;
21     build(x * 2, l, mid);
22     build(x * 2 + 1, mid + 1, r);
23     tree[x].pre = tree[x * 2].pre + tree[x * 2 + 1].pre;
24 }
25 void spread(int p)
26 {
27     if (tree[p].add)
28     {
29         tree[p * 2].pre += tree[p].add * (tree[p * 2].r - tree[p * 2].l + 1);
30         tree[p * 2 + 1].pre += tree[p].add * (tree[p * 2 + 1].r - tree[p * 2 + 1].l + 1);
31         tree[p * 2].add += tree[p].add;
32         tree[p * 2 + 1].add += tree[p].add;
33         tree[p].add = 0;
34     }
35 }
36 void add(int p, int x, int y, int z)
37 {
38     if (x <= tree[p].l && y >= tree[p].r)
39     {
40         tree[p].pre += (long long)z * (tree[p].r - tree[p].l + 1);
41         tree[p].add += z;
42         return;
43     }
44     spread(p);
45     int mid = tree[p].l + tree[p].r >> 1;
46     if (x <= mid)
47         add(p * 2, x, y, z);
48     if (y > mid)
49         add(p * 2 + 1, x, y, z);
50     tree[p].pre = tree[p * 2].pre + tree[p * 2 + 1].pre;
51 }
52 long long sum(int p, int x, int y)
53 {
54     if (x <= tree[p].l && y >= tree[p].r)
55         return tree[p].pre;
56     spread(p);
57     int mid = tree[p].l + tree[p].r >> 1;
58     long long ans = 0;
59     if (x <= mid)
60         ans += sum(p * 2, x, y);
61     if (y > mid)
62         ans += sum(p * 2 + 1, x, y);
63     return ans;
64 }
65 int main()
66 {
67     int n, m;
68     cin >> n >> m;
69     for (int i = 1;i<=n;i++)
70     {
71         cin >> a[i];
72     }
73     build(1, 1, n);
74     for (int i = 1;i<=m;i++)
75     {
76         int q, x, y, z;
77         cin >> q;
78         if(q==1)
79         {
80             cin >> x >> y >> z;
81             add(1, x, y, z);
82         }
83         else
84         {
85             cin >> x >> y;
86             cout << sum(1, x, y) << endl;
87         }
88     }
89     return 0;
90 }
View Code

 四十一·矩阵快速幂

 1 #include <iostream>
 2 #include <cstring>
 3 #define mod 1000000007
 4 #define ll long long
 5 using namespace std;
 6 struct Mat
 7 {
 8     ll m[101][101];
 9 };        
10 Mat a, e; 
11 ll n, p;
12 Mat Mul(Mat x, Mat y) 
13 {
14     Mat c;
15     for (int i = 1; i <= n; i++)
16     {
17         for (int j = 1; j <= n; j++)
18         {
19              c.m[i][j] = 0;
20         }
21     }
22     for (int i = 1; i <= n; i++)
23     {
24         for (int j = 1; j <= n; j++)
25         {
26              for (int k = 1; k <= n; k++)
27              {
28                  c.m[i][j] = c.m[i][j] % mod + x.m[i][k] * y.m[k][j] % mod;
29              }
30         }
31     }
32     return c;
33 }
34 Mat pow(Mat x, ll y) 
35 {
36     Mat ans = e;
37     while (y)
38     {
39         if (y & 1)
40             ans = Mul(ans, x);
41         x = Mul(x, x);
42         y >>= 1;
43     }
44     return ans;
45 }
46 
47 int main()
48 {
49     cin >> n >> p;
50     for (int i = 1; i <= n; i++)
51     {
52         for (int j = 1; j <= n; j++)
53         {
54             cin >> a.m[i][j];
55         }
56     }
57     for (int i = 1; i <= n; i++)
58     {
59         e.m[i][i] = 1;
60     }
61     Mat ans = pow(a, p);
62     for (int i = 1; i <= n; i++)
63     {
64         for (int j = 1; j <= n; j++)
65         {
66             cout << ans.m[i][j] % mod << " ";
67         }
68         cout << endl;
69     }
70     return 0;
71 }
View Code

 

 四十二·退役前最后的一次更新  进制转换,10 转其他

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int n,m;
 5 char f[20] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};
 6 void  zhuan(int n,int m)
 7 {
 8     if(n==0)
 9     {
10         return;
11     }
12     if(n>0||n%m==0)
13     {
14         zhuan(n / m, m);
15         cout << f[n % m];
16     }
17     else
18     {
19         zhuan(n / m + 1, m);
20         cout << f[-m+n % m];
21     }
22     
23 }
24 int main()
25 {
26     cin >> n;
27     cin >> m;
28     cout << n << "=";
29     zhuan(n, m);
30     cout << "(base" << m << ")" << endl;
31     return 0;
32 }
View Code

 

 

 

 

 

 

 

 

posted @ 2019-10-22 20:52  2529102757  阅读(410)  评论(0编辑  收藏  举报