2013.10.10模版

来源:互联网 发布:网络用语996什么意思 编辑:程序博客网 时间:2024/06/05 02:18

目录

数据范围...5

数论...6

素数...6

个数pi(x)~x/ln(x)...6

排列组合常见公式...8

组合恒等式...9

判断与分解...9

Millar Rabin+Pollard rho算法...9

卡特兰数:...12

大数类...12

数学公式:...18

A^B%C.18

正整数n的因子之和...18

勾股数...18

公式...18

勾股数组数N..18

欧拉常数:...19

欧拉定理...19

单点判断...19

打表...19

公约数...20

gcd Stein算法...20

位运算gcd.20

扩展欧几里德定理...20

约瑟夫环...21

汉诺塔...21

二分算法...22

斐波拉契数列...22

Coj 1053斐波拉契数列+矩阵连乘...23

各种定理...24

欧拉定理...24

威尔逊定理...24

费马小定理...24

反素数...24

定义...24

性质...24

反素数表...24

Zoj2562 最大反素数...25

高斯消元...25

容斥原理...27

DP.28

母函数模版...28

最长(非)上升子序列...28

二分+贪心...28

On^2...30

最长公共子序列...30

最长公共上升子序列...31

O(n^3).31

O(n^2).32

最长公共子串...32

最长回文子串Hdu3068.33

最大m子段和...34

双调DP codefource213C.34

三方格取数...35

背包九讲...36

0-1背包 POJ 3624.36

离散化+01背包 Interview Arrangement.37

完全背包 hdu 1114.38

多重背包 hdu 2191二进制法...39

单调队列 poj2823.39

单调队列多重背包hdu 2191.41

二维背包hdu3496.41

分组背包hdu1712.42

依赖背包...42

1.转化为分组背包方法 NOIP2006金明的预算方案...42

2. 二附件依赖背包方法...44

数据结构...46

星期几...46

前向星建图...46

STL. 46

vector基本用法...46

set(multiset)的基本用法...47

最小生成树poj1251.49

排序... 51

优先队列...51

快速排序函数...51

归并排序函数...51

ST算法...52

poj 3264 Balanced Lineup 最值...52

线段树...53

Hdu3397 区间取反...53

Coj 1478 第K大值(update)...57

Uva11983 矩形k次交...60

Hdu1542 线段树扫描线矩形面积并...63

树状数组...65

Hdu1166 区间求和...65

最大子矩阵...66

poj1050 最大子矩阵...66

字符串...68

函数... 68

Sscanf函数...68

Sprintf函数...69

Strtok函数...69

KMP算法...70

找出以第i个字符为起始位置的最小字典序字符串...70

计算几何...71

几何公式...71

三角形:71

四边形:71

n边形:71

:71

棱柱:72

棱锥:72

棱台:72

圆柱:72

圆锥:72

圆台:72

最近点对 Hdu1007.73

叉乘法求任意多边形面积...74

博弈... 75

威佐夫博弈hdu~1527/poj~1067.75

Nim博弈...75

SG函数...76

思路... 76

Hdu 1536.76

图论... 78

搜索... 78

Hdu 1428 优先队列广搜+记忆化搜索...78

其他... 80

补码... 80

输入输出...80

含空格字符串输入...80

数字外挂输入:...80

文件输入输出...80

注意:...80

做题方法...81

数学... 81

动态规划...81

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

数据范围

char               -128 ~ +127 (1 Byte)
short              -32767 ~ + 32768 (2 Bytes)
unsigned short     0 ~ 65536 (2 Bytes)
int                -2147483648~ +2147483647 (4 Bytes)
unsigned int       0 ~4294967295 (4 Bytes)
long == int
long long          -9223372036854775808~ +9223372036854775807 (8 Bytes)
double             1.7* 10^308 (8 Bytes)

unsigned int       0~4294967295
unsigned long long的最大值:1844674407370955161

__int64的最大值: 9223372036854775807
__int64的最小值: -9223372036854775808
unsigned __int64的最大值:18446744073709551615

 

 

数论

素数

O(n)打表

const int NS=1000100;

int isprime[NS],pri[NS],top=0;

void prime_table()

{

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

    {

       if (!isprime[i]) pri[top++]=i;

       for (int j=0;j<top&&i*pri[j]<NS;j++)

       {

           isprime[i*pri[j]]=1;

           if (i%pri[j]==0) break;

       }

    }

}

 

数量分布 (pi(x)~x/ln(x)

 

 

 

排列组合常见公式 

组合恒等式

 

 

 

 

 

位数计算

n!最右边非零位

给一个正整数N(N为大整数),输出最右边非零的数字

代码:0//大整数以string的形式传入

int Last_nonzero_Digit_in_N(string str)

{

    intmod[20]={1,1,2,6,4,2,2,4,2,8,

                4,4,8,4,6,8,8,6,8,2};

    int a[1000];

    int i, c, t=1,len=str.length();

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

        a[i] = str[len - 1 -i] –‘0’;

    while (len)

    {

        len -= !a[len - 1];

        t = t * mod[a[1] % 2 *10 + a[0]] % 10;

        for (c = 0, i = len -1; i >= 0; i–)

            c = c * 10 + a[i],a[i] = c / 5, c %= 5;

    }

    return t;

}

Sterling公式

最高位 (int)10^(log10(n)- (int)log10(n))

Millar Rabin+Pollard rho算法

#include<cstdio>

#include<cstdlib>

#include<iostream>

typedef long long LL;

#define MAX((LL)1<<61)

 

const int CT=201;

const int Times=50;

 

LL min_factor;

 

LL multi(LL aa,LL bb,LLmod)

{

    LL res=0;

    while (bb>0)

    {

        if (bb&1) res=(res+aa)%mod;

        bb>>=1;

        aa=(aa<<1)%mod;

    }

    return res;

}

 

LL quick_mod(LL aa,LL bb,LLmod)

{

    LL res=1;

    aa%=mod;

    while (bb>0)

    {

        if (bb&1) res=multi(res,aa,mod);

        bb>>=1;

        aa=multi(aa,aa,mod);

    }

    return res;

}

 

int judge(LL aa,LL n)

{

    int c=0;

    LL bb=n-1;

    while (!(bb&1)) c++,bb>>=1;

    LL ans=quick_mod(aa,bb,n);

    if (ans==1||ans==(n-1)) return 0;

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

    {

        ans=multi(ans,ans,n);

        if (ans==n-1) return 0;

    }

    return 1;

}

 

int Miller_Rabin(LL n)

{

    LL rd;

    if (n<2) return 0;

    if (n<4) return 1;

    if (!(n&1)) return 0;

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

    {

       rd=(LL)((double)rand()/RAND_MAX*(n-2)+2);

        if (judge(rd,n)) return 0;

    }

    return 1;

}

 

LL gcd (LL aa,LL bb)

{

    return bb==0?aa:gcd(bb,aa%bb);

}

 

LL pollard_rho(LL n,int c)

{

    LL d,x,y,i=1,k=2;

    y=x=(LL)((double)rand()/RAND_MAX*(n-1)+1);

    while (1)

    {

        i++;

        x=(multi(x,x,n)+c)%n;

        d=gcd(y-x,n);

        if (d>1&&d<n) return d;

        if (y==x) return n;

        if (i>=k)

        {

            y=x;

            k<<=1;

        }

    }

}

 

void Fin(LL n,int c)

{

    if (n==1) return ;

    if (Miller_Rabin(n))

    {

        min_factor=n<min_factor?n:min_factor;

        return ;

    }

    LL k=n;

    while (k>=n) k=pollard_rho(k,c--);

    Fin(k,c);

    Fin(n/k,c);

}

 

int main()

{

    int T;

    LL n;

    scanf("%d",&T);

    while (T--)

    {

        scanf("%I64d",&n);

        if (Miller_Rabin(n))

            printf("Prime\n");

        else

        {

            min_factor=MAX;

            Fin(n,CT);

           printf("%I64d\n",min_factor);

        }

    }

    return 0;

}

 

卡特兰数:

1通项公式:h(n)=C(n,2n)/(n+1)=(2n)!/((n!)*(n+1)!)

2递推公式:h(n)=((4*n-2)/(n+1))*h(n-1); h(n)=h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)*h(0).

3前几项为:h(0)=1,h(1)=1,h(2)=2,h(3)=5,h(4)=14,h(5)=42,......

 

大数类

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <string>

#include <algorithm>

using namespace std;

 

const int MAXN = 500;

 

struct bign

{

       intlen, s[MAXN];

       bign()

       {

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

              len= 1;

       }

       bign(int num) { *this = num; }

       bign(const char *num) { *this = num; }

       bignoperator = (const int num)

       {

              chars[MAXN];

              sprintf(s,"%d", num);

              *this= s;

              return*this;

       }

       bignoperator = (const char *num)

       {

              for(inti = 0; num[i] == '0'; num++);//去前导0

              len= strlen(num);

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

           s[i] = num[len-i-1] - '0';

              return*this;

       }

       bignoperator + (const bign &b) const //+

       {

              bignc;

              c.len= 0;

              for(inti = 0, g = 0; g || i < max(len, b.len); i++)

              {

                     intx = g;

                     if(i< len) x += s[i];

                     if(i< b.len) x += b.s[i];

                     c.s[c.len++]= x % 10;

                     g= x / 10;

              }

              returnc;

       }

       bignoperator += (const bign &b)

       {

              *this= *this + b;

              return*this;

       }

       voidclean()

       {

              while(len> 1 && !s[len-1]) len--;

       }

       bignoperator * (const bign &b) //*

       {

              bignc;

              c.len= len + b.len;

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

                     for(intj = 0; j < b.len; j++)

                            c.s[i+j]+= s[i] * b.s[j];

              for(inti = 0; i < c.len; i++)

              {

                     c.s[i+1]+= c.s[i]/10;

                     c.s[i]%= 10;

              }

              c.clean();

              returnc;

       }

       bignoperator *= (const bign &b)

       {

              *this= *this * b;

              return*this;

       }

       bignoperator - (const bign &b)

       {

              bignc;

              c.len= 0;

              for(inti = 0, g = 0; i < len; i++)

              {

                     intx = s[i] - g;

                     if(i< b.len) x -= b.s[i];

                     if(x>= 0) g = 0;

                     else

                     {

                            g= 1;

                            x+= 10;

                     }

                     c.s[c.len++]= x;

              }

              c.clean();

              returnc;

       }

       bignoperator -= (const bign &b)

       {

              *this= *this - b;

              return*this;

       }

       bignoperator / (const int b)

       {

              bignc;

              intf = 0;

              for(inti = len-1; i >= 0; i--)

              {

                     f= f*10+s[i];

                     c.s[i]=f/b;

                     f=f%b;

              }

              c.len= len;

              c.clean();

              returnc;

       }

       bignoperator / (const bign &b)

       {

              bignc, f = 0;

              for(inti = len-1; i >= 0; i--)

              {

                     f= f*10;

                     f.s[0]= s[i];

                     while(f>= b)

                     {

                            f-= b;

                            c.s[i]++;

                     }

              }

              c.len= len;

              c.clean();

              returnc;

       }

       bignoperator /= (const bign &b)

       {

              *this  = *this / b;

              return*this;

       }

       bignoperator % (const bign &b)

       {

              bignr = *this / b;

              r= *this - r*b;

              returnr;

       }

       bignoperator %= (const bign &b)

       {

              *this= *this % b;

              return*this;

       }

       bignoperator ^ (const int & n) //大数的n次方运算

    {

       bign t(*this),ret(1);

       if(n<0) exit(-1);

       if(n==0) return 1;

       int m=n;

       while (m)

       {

           if (m&1) ret=ret*t;

           t=t*t;

           m>>=1;

       }

       return ret;

    }

       booloperator < (const bign &b)

       {

              if(len!= b.len) return len < b.len;

              for(inti = len-1; i >= 0; i--)

                     if(s[i]!= b.s[i]) return s[i] < b.s[i];

              returnfalse;

       }

       booloperator > (const bign &b)

       {

              if(len!= b.len) return len > b.len;

              for(inti = len-1; i >= 0; i--)

                     if(s[i]!= b.s[i]) return s[i] > b.s[i];

              returnfalse;

       }

       booloperator == (const bign &b) {

              return!(*this > b) && !(*this < b);

       }

       booloperator != (const bign &b) {

              return!(*this == b);

       }

       booloperator <= (const bign &b) {

              return*this < b || *this == b;

       }

       booloperator >= (const bign &b) {

              return*this > b || *this == b;

       }

       stringstr() const

       {

              stringres = "";

              for(inti = 0; i < len; i++) res = char(s[i]+'0') + res;

              returnres;

       }

};

 

istream& operator >> (istream&in, bign &x)

{

       strings;

       in>> s;

       x= s.c_str();

       returnin;

}

 

ostream& operator << (ostream&out, const bign &x)

{

       out<< x.str();

       returnout;

}

 

int main()

{

       bigna, b, c, d, e, f, g, h, k;

       while(cin>>a>>b)

       {

              a.clean(),b.clean();

              c= a+b, d = a-b;

              e= a*b, f = a/b;

              g= a%b, h = a/999;

              k= a^10;

       }

       return0;

}

 

 

数学公式:

C(m,n)=C(m-1,n)+C(m-1,n-1)

求和公式,k =1..n

1. sum( k^2 ) =n(n+1)(2n+1)/6

2. sum( (2k-1)^2 ) =n(4n^2-1)/3

3. sum( k^3 ) =(n(n+1)/2)^2

4. sum( (2k-1)^3 ) =n^2(2n^2-1)

5. sum( k^4 ) =n(n+1)(2n+1)(3n^2+3n-1)/30

6. sum( k^5 ) =n^2(n+1)^2(2n^2+2n-1)/12

7. sum( k(k+1) ) =n(n+1)(n+2)/3

8. sum( k(k+1)(k+2) ) =n(n+1)(n+2)(n+3)/4

9. sum( k(k+1)(k+2)(k+3) )= n(n+1)(n+2)(n+3)(n+4)/5

10. sum(1/(k^2)) =π^2/6 (n->无穷);

11. sum(k*x^k)=[x-(1+n)x^(n+1)+nx^(n+2)]/(1-x)^2. (x>1);

 

正整数n的因子之和

n=p1e1p2e2prer

Sum=(1+p1+p12++p1e1)*(1+p2+p22++p2e2) **(1+pr+pr2++prer)

 

勾股数

公式

局部公式:a=2mn  b=m^2-n^2  c=m^2+n^2 可以得到所有的基本勾股数

完全公式:a=m,b=(m^2 / k - k) / 2,c=(m^2 / k + k) / 2

其中m ≥3

1、当m确定为任意一个 ≥3的奇数时,k={1,m^2的所有小于m的因子}

2、当m确定为任意一个 ≥4的偶数时,k={m^2 / 2的所有小于m的偶数因子

勾股数组数N

一个大于1的正整数n,如果它的标准分解式为n=p1^m1×p2^m2×……×pr^mr,那么它的正因数个数为N=(m1+1)×(m2+1)×……×(mr+1);依据定理,易得以下结论

  当a给定时,不同勾股数组a,b,c的组数N等于①式中k的可取值个数

  1、取奇数a=p1^m1×p2^m2×……×pr^mr,其中k={1,a^2的所有小于a的因子},则k的可取值个数:

  N=[(2m1+1)×(2m2+1)×……×(2mr+1)-1]/2

  2、取偶数a=2^m0×p1^m1×p2^m2×……×pr^mr,其中k={a^2 / 2的所有小于a的偶数因子},则k的可取值个数:

  N=[(2m0-1)×(2m1+1)×(2m2+1)×……×(2mr+1)-1]/2

其中,p1,p2,……,pr为互不相同的奇素数,m0,m1,……,mr为幂指数。

欧拉常数:

S=1+1/2+1/3+……=0.577215,66490,15328,60606,51209,00824,02431,04215,93359,39923,59880,57672,34884,86772,67776,64670,93694,70632,91746,74951,46314,47249,80708,24809,60504,01448,65428,36224,17399,76449,23536,25350,03337,42937,33773,76739,42792,59525,82470

极限S=lim[1+1/2+1/3+…+1/n-ln(n)](n→∞)存在

欧拉函数

单点判断

int eular(int n)

{

   intret=1,i;

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

   if(n%i==0)

   {

      n/=i,ret*=i-1;

      while(n%i==0)

      n/=i,ret*=i;    

   }

   if(n>1) ret*=n-1;

   returnret;

}

打表

constint N=1000010;

int phi[N+1];

void eular()

{

    inti,j;

    for(i=1;i<=N;i++) phi[i]=i;

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

    {

        if (phi[i]==i)

        {

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

           {

               phi[j]=phi[j]/i*(i-1);   

           }         

        }   

    }    

}

 

公约数

gcdStein算法

int gcd(int a, int b)

{

   if(a==0) return b;

   if(b== 0) return a;

   if(a%2==0&&b%2==0) return gcd(a>>1,b>>1)<<1;

   elseif(a%2==0) return gcd(a>>1,b);

   elseif(b%2==0) return gcd(a,b>>1);

   elsereturn gcd((a>b?(a-b):(b-a)),(a<b?a:b));

}

位运算gcd

int binary_gcd(int x,int y)

{

   if(x==0) return y;

   if(y==0) return x;

   intcnt=0,tmp;

   while((x|y)&1==0) x>>=1,y>>=1,cnt++;

   while(x&1==0) x>>=1;

   while(y)

   {

       while (y&1==0) y>>=1;

       int tmp=y;

       y=y>x?y-x:x-y;

       x=tmp;

   }

   return x<<=cnt;

}

扩展欧几里德定理

int exGcd(int a, int b, int &x, int &y)

{

   if (b == 0)

       {

       x = 1;

       y = 0;

       return a;

       }

   int r = exGcd(b, a % b, x,y);

   int t = x;

   x = y;

   y = t - a / b * y;

   return r;

}

p * a+q * b = c的一组解p1 = p0*(c/Gcd(a,b)),q1 =q0*(c/Gcd(a,b))p * a+q* b = c的其他整数解满足:

p = p1 +b/Gcd(a, b) * t

q = q1 -a/Gcd(a, b) * t(其中t为任意整数)

pq就是p * a+q* b = c的所有整数解。

 

约瑟夫环

   scanf("%d%d",&n, &m);

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

       s=(s+m)%i;

 

二分算法

int Fin(double key) //返回<=key的下标

{

   intl=0,r=n-1;

   while(l<r)

   {

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

       if (A[m]==key) return m;

       else if (A[m]>key) r=m-1;

       else if (m==n-1||A[m+1]>key) return m;

       else l=m+1;

   }

   return r;

}

 

fibonacci数列

F(n)=(1/5)*{[(1+5)/2]^n- [(1-5)/2]^n}

F(n) = [ (( sqrt ( 5 ) + 1 ) / 2) ^ n ]其中[ x ]表示取距离 x 最近的整数。

1.gcd(fib(n),fib(m))=fib(gcd(n,m)) 

2.如果fib(k)能被x整除,则fib(k*i)都可以被x整除。

3.f(0)+f(1)+f(2)+…+f(n)=f(n+2)-1

4.f(1)+f(3)+f(5)+…+f(2n-1)=f(2n)

5.f(2)+f(4)+f(6)+…+f(2n) =f(2n+1)-1

6.[f(0)]^2+[f(1)]^2+…+[f(n)]^2=f(n)·f(n+1)

7.f(0)-f(1)+f(2)-…+(-1)^n·f(n)=(-1)^n·[f(n+1)-f(n)]+1

8.f(m+n)=f(m-1)·f(n-1)+f(m)·f(n)

9.[f(n)]^2=(-1)^(n-1)+f(n-1)·f(n+1)

10.f(2n-1)=[f(n)]^2-[f(n-2)]^2

11.3f(n)=f(n+2)+f(n-2)

12. f(2n-1)=f(2n)*f(2n-2)+1

13.f(2n-2m-2)[f(2n)+f(2n+2)]=f(2m+2)+f(4n-2m) [ n〉m≥-1,且n≥1]

 

定理

欧拉定理

A^X% C= A^(X%phi(C)+phi(C)) % C (X>=phi(C))

n,a为正整数,且n,a互质,(a,n) = 1,则a^φ(n) 1 (modn)

欧拉定理表明,若n,a为正整数,且n,a互质,(a,n) = 1,则a^φ(n) 1 (modn)

a是不能被质数p整除的正整数,则有a^(p-1) 1 (modp)

当模有原根时,它有个原根。

 

当且仅当p为素数时:( p -1 )! ≡ -1 ( mod p )

费马小定理

假如p是质数,且(a,p)=1,那么 a^(p-1) ≡1(mod p)

假如p是质数,则:a^p ≡a(mod p)

中国剩余定理

1、若a和b是正整数,则2^a-1模2^b-1的最小正剩余是2^r-1,其中r是a模b的最小正剩余。2、(2^a-1和2^b-1)= 2^(a,b)-1.正整数2^a-1和2^b-1是互素的,当且仅当a与b是互素的。

3、给定两两互素的模m1,m2,…,mr,一个小于M=m1m2…mr的正整数n由它的模mj最小正剩余唯一决定,其中j=1,2,…,r.

反素数

定义

对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x)。

性质

性质一:一个反素数的质因子必然是从2开始连续的质数.

性质二:p=2^t1*3^t2*5^t3*7^t4.....必然t1>=t2>=t3>=....

反素数表

int rprim[35][2] = {

    498960,200,332640,192,277200,180,221760,168,166320,160,

     110880,144,83160,128,55440,120,50400,108,45360,100,

    27720,96,25200,90,20160,84,15120,80,10080,72,

    7560,64,5040,60,2520,48,1680,40,1260,36,

    840,32,720,30,360,24,240,20,180,18,

    120,16,60,12,48,10,36,9,24,8,

     12,6,6,4,4,3,2,2,1,1};

 

const int size=500000;

int isprime[size+10],atp[size+10][2];

void antiprime()

{

     int i,j;

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

         for(j=i;j<=size;j+=i)

             atp[j][0]++;

    

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

     {

         atp[i][1]=i;

         if (atp[i][0]<atp[i-1][0])

         {

           atp[i][0]=atp[i-1][0];

           atp[i][1]=atp[i-1][1];

         }

         else if(atp[i][0]==atp[i-1][0]&&

                 atp[i][1]>atp[i-1][1])

                atp[i][1]=atp[i-1][1];

     }

}

高斯消元

Hdu 4200

int n,d,row,col,ans;

char g[110][110];

int num[110];

 

void gauss()

{

    inti,j,k;

    for(col=row=1;col<=n;col++)

    {

        for (i=row;i<=n;i++) if (g[i][col]) break;

        if (i>n) continue;

        if (i!=row) for (j=col;j<=n+1;j++)

        k=g[i][j],g[i][j]=g[row][j],g[row][j]=k; 

        for (i=row+1;i<=n;i++) if (g[i][col])

        for (j=col;j<=n+1;j++) g[i][j]^=g[row][j];

        row++;

    }

    return ;

}

 

void dfs(int k)

{

    if(k<=n)

    {

       num[k]=1,dfs(k+1);

       num[k]=0,dfs(k+1);        

    }    

    else

    {

        int i,j;

        for (i=row-1;i>0;i--)

        {

            k=g[i][n+1];

            for (j=i+1;j<=n;j++) k^=g[i][j]&&num[j];

            num[i]=k;     

        }   

        for (i=1,k=0;i<=n;i++) k+=num[i];

        ans=min(k,ans);

    }

    return ;

}

 

int main()

{

   inti,j,k,t,L,R;

   scanf("%d",&t);

   while(t--)

   {

         scanf("%d %d",&n,&d);

         memset(g,0,sizeof(g));

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

         {

             scanf("%d",&g[i][n+1]);

             L=max(1,i-d);

             R=min(n,i+d);

             for (j=L;j<=R;j++) g[j][i]=1;   

         }     

         ans=110,gauss();

         for (i=row;i<=n;i++) if (g[i][n+1]) break;

         if (i<=n) ans=-1;

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

         {

             if (!g[i][i])

             {

                for (j=i+1;j<=n;j++) if (g[i][j]) break;

                if (j>n) break;

                for (k=1;k<=n;k++)

                R=g[k][j],g[k][j]=g[k][i],g[k][i]=R;            

             }   

         }

         if (ans>0) dfs(row);

         printf(ans==-1?"impossible\n":"%d\n",ans);

   }

   return 0;

}

 

DP

母函数模版

#include<iostream>

#include<stdio.h>

using namespace std;

const int maxn=121;

int main()

{

   intc[maxn],d[maxn];

   inti,j,k;

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

       c[i]=1,d[i]=0;

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

   {

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

       {

           for(k=0; k+j<maxn; k+=i)

           {

               d[j+k]+=c[j];

           }

       }

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

       {

           c[j]=d[j];

           d[j]=0;

       }

   }

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

   {

       printf("%d\n",c[k]);

   }

   return 0;

}

 

 

 

最长公共上升子序列

O(n^3)

#include<iostream>

usingnamespace std;

constint MAX=501;

//dp[i]表示a中第i个元素的最优解个数,只不过ai需满足bj==ai;

intgcis(int a[], int la, int b[], int lb)

{

    int i,j,k,mx,dp[MAX];

    memset(dp, 0, sizeof(dp));

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

        for(j=1; j<=lb; j++)

            if(a[i-1]==b[j-1])

                for(k=1,dp[j]=1; k<j; k++)

                    if(b[k-1]<b[j-1]&&dp[k]+1>dp[j])

                        dp[j]=dp[k]+1;

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

        if (dp[0]<dp[i])

            dp[0]=dp[i];

    return dp[0];

}

intmain(void)

{

    int n,am,bm,a[MAX],b[MAX],i,j;

    cin>>n;

    j=0;

    while(n--)

    {

        j++;

        cin>>am;

        for(i=0; i<am; i++) cin>>a[i];

        cin>>bm;

        for(i=0; i<bm; i++) cin>>b[i];

        am=gcis(a,am,b,bm);

       printf(j==1?"%d\n":"\n%d\n",am);

    }

    return 0;

}

 

O(n^2)

int LCIS(int a[],int b[],int la,int lb)

{

   intmaxs;

   memset(f,0,sizeof(f));

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

   {

       maxs=0;

       for (int j=1;j<=lb;j++)

       {

           if (a[i]>b[j]&&maxs<f[j]) maxs=f[j];

           if (a[i]==b[j]) f[j]=maxs+1;

       }

   }

   for(int j=1;j<=lb;j++) f[0]=Max(f[0],f[j]);

   return f[0];

}

最长公共子串

char* LCS(char left[],char right[])

{

   int lenLeft=strlen(left),lenRight=strlen(right),k;

   char *c=(char *)malloc(lenRight),*p;

   int start,end,len,i,j;

   end=len=0;//len表示最长公共子串的长度

   for(i=0; i<lenLeft; i++) //串1从前向后比较

    {

       for(j=lenRight-1; j>=0; j--) //串2从后向前比较

       {

           if(left[i] == right[j])//元素相等时

           {

                if(i==0||j==0) c[j]=1;

                else c[j]=c[j-1]+1;

           }

           else

                c[j] = 0;

           if(c[j] > len)

           {

                len=c[j];

                end=j;

           }

       }

    }

   start=end-len+1;

    p=(char*)malloc(len+1);

   for (i=start; i<=end; i++)

        p[i-start] = right[i];

   p[len]='\0';

   return p;

}

最长回文子串 Hdu3068

int solve(char *str)

{

   intmx=0,res=0,id;

   intn=strlen(str);

   c[0]='$',c[1]='#';

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

   c[i*2+2]=str[i],c[i*2+3]='#';

   n=n+n+2;

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

   {

       p[i]=mx>i?min(p[id+id-i],mx-i):1;

       for (;c[i-p[i]]==c[i+p[i]];p[i]++);

       if (p[i]+i>mx) mx=p[i]+i,id=i;

       if (p[i]>res) res=p[i];

   }

   return res-1;

}

最大m子段和

LL MaxSum(int n,int m,LL *a) //数组an个元素必须取m

{

   inti,j,f=0;

   LLans;

   if(n<m||m<1) return 0;

   for(j=0; j<=n; j++) dp[0][j]=dp[1][j]=0;

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

   {

       f=1-f;

       dp[f][i]=dp[1-f][i-1]+a[i];

       ans=dp[1-f][i-1];

       for (j=i+1; j<=n-m+i; j++)

       {

           ans=Max(ans,dp[1-f][j-1]);

           dp[f][j]=Max(dp[f][j-1],ans)+a[j];

       }

   }

   for(ans=-INF,i=m; i<=n; i++) ans=Max(ans,dp[f][i]);

   return ans;

}

 

背包

单调队列 poj2823

#include "stdio.h"

#include "string.h"

const int M=1000005;

int arr[M];

int Minq[M],Maxq[M];

int Q[M],Inq[M];

int n,k;

void Min()

{

   inthead=1,tail=0;

   inti;

 

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

   {

       while(head<=tail && Q[tail]>arr[i])

           tail--;

       tail++;

       Q[tail]=arr[i];

       Inq[tail]=i;

       if(i>=k)

       {

           while(Inq[head]<=i-k) head++;

           Minq[i-k]=Q[head];

       }

   }

}

void Max()

{

   inthead=1,tail=0;

   inti;

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

   {

       while(head<=tail && Q[tail]<arr[i])

           tail--;

       tail++;

       Q[tail]=arr[i],Inq[tail]=i;

       if(i>=k)

       {

           while(Inq[head]<=i-k)

               head++;

           Maxq[i-k]=Q[head];

       }

   }

}

int main()

{

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

   {

       if(k>n) k=n;

       int i;

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

           scanf("%d",&arr[i]);

       Min();

       Max();

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

           printf("%d%c", Minq[i], (i < n - k) ? ' ' : '\n');

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

           printf("%d%c", Maxq[i], (i < n - k) ? ' ' : '\n');

   }

   return 0;

}

单调队列多重背包hdu 2191

int main()

{

   intn,m,cas,i,j,k,y,head,tail;

   intp[N],w[N],s[N],f[N],u[N],v[N];

   scanf("%d",&cas);

   while(cas--)

   {

       scanf("%d%d",&n,&m);

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

           scanf("%d%d%d",&p[i],&w[i],&s[i]);

       for(i=0; i<=n; i++) f[i]=0;

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

       {

           for(j=0; j<p[i]; j++)

           {

               head=0,tail=-1;

               for(k=0; k<=(n-j)/p[i]; k++)

               {

                   y=f[j+k*p[i]]-k*w[i];

                   while(head<=tail&&u[tail]<=y) tail--;

//去掉队列中不可能为最大值大数据

                   u[++tail]=y,v[tail]=k;

                   while(head<=tail&&v[tail]-v[head]>s[i]) head++;

//保证队列首尾差值数量不大于当前物品的数量

                   f[j+k*p[i]]=u[head]+k*w[i];

               }

           }

       }

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

   }

}

分组背包

分组背包每组至少选择一个状态转移方程如下:

dp[i][t]=max(dp[i][t],dp[i][t-p[i][j]]+v[i][j]);

dp[i][t]=max(dp[i][t],dp[i-1][t-p[i][j]]+v[i][j]);

棋盘覆盖

1*len长度状态搜索

void dfs(int pre,int now,int pos,int len)  //p_len=len^len

{

    if (pos<0) return ;

    if (pos==0)

    {

        state[top][0]=pre,state[top++][1]=now;

        return ;

    }

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

   dfs(pre*len+i,now*len+((i+len-1)%len),pos-1,len);

   dfs(pre*p_len,now*p_len,pos-len,len);

}

 

数据结构

日期函数

intdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};

struct date{

       intyear,month,day;

};

//判闰年

inline int leap(int year){

       return(year%4==0&&year%100!=0)||year%400==0;

}

//判合法性

inline int legal(date a){

       if(a.month<0||a.month>12)

              return0;

       if(a.month==2)

              returna.day>0&&a.day<=28+leap(a.year);

       returna.day>0&&a.day<=days[a.month-1];

}

//比较日期大小

inline int datecmp(date a,date b){

   if(a.year!=b.year)

          return a.year-b.year;

   if(a.month!=b.month)

          return a.month-b.month;

  return a.day-b.day;

}

//返回指定日期是星期几

int weekday(date a){

       inttm=a.month>=3?(a.month-2):(a.month+10);

       intty=a.month>=3?a.year:(a.year-1);

       return(ty+ty/4-ty/100+ty/400+(int)(2.6*tm-0.2)+a.day)%7;

}

//日期转天数偏移

int date2int(date a){

       intret=a.year*365+(a.year-1)/4-(a.year-1)/100+(a.year-1)/400,i;

       days[1]+=leap(a.year);

       for(i=0;i<a.month-1;ret+=days[i++]);

       days[1]=28;

       returnret+a.day;

}

//天数偏移转日期

date int2date(int a){

       dateret;

       ret.year=a/146097*400;

       for(a%=146097;a>=365+leap(ret.year);a-=365+leap(ret.year),ret.year++);

       days[1]+=leap(ret.year);

       for(ret.month=1;a>=days[ret.month-1];a-=days[ret.month-1],ret.month++);

       days[1]=28;

       ret.day=a+1;

       returnret;

}

星期几

W[][20]={"monday","tuesday", "wednesday","thursday","friday", "saturday", "sunday"}

int Week(int y,int m,int d) //y表示年份,m表示月份,d表示天数

{

   int a;

   // 1月2月当作前一年的13,14月

    if (m == 1 || m == 2)

    m+= 12,y--;

   // 判断是否在1752年9月3日之前

   if ((y < 1752) || (y == 1752 && m < 9) ||

       (y == 1752 && m == 9 && d < 3))

       a = (d + 2*m + 3*(m+1)/5 + y + y/4 +5) % 7;

   else

       a = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400)%7;

   return a;

}

STL

vector基本用法

1.sort(vi.begin(), vi.end()); // 从小到大
2.reverse(vi.begin(),vi.end()) // 从大到小
3.vector<int>::iterator it;
4.it=find(v.begin(),v.end(),value);
5.v.push_back(value); void pop_back();
6.v.empty(); v.size();v..resize();
7.for(vector<string>::size_type i = 0;;);
8.v.erase(pos) // 删除pos位置的数据,传回下一个数据的位置;
9.v.erase(v.begin(),v.end());
10.v.clear() ;  v.front() ;
11.v.insert(pos,elem)  在pos(指针)位置插入一个elem拷贝;
12.v.insert(pos,n,elem) // 在pos位置插入n个elem数据,无返回值 ;
13.v.insert(pos,beg,end) // 在pos位置插入在[beg,end)区间的数据;无返回值; 
14.v.rend() 传回一个逆向队列的最后一个数据的下一个位置; 
15.v.max_size() 返回容器中最大数据的数量; 
16.v.rbegin() 传回一个逆向队列的第一个数据;
17.v.assign(beg,end)  将(beg; end)区间中的数据赋值给c;
18.v.assign(n,elem)  将n个elem的拷贝赋值给c;   
19.v. at(idx) 传回索引idx所指的数据,如果idx越界,抛出out_of_range;
20.c.erase(beg,end) 删除[beg,end)区间的数据,传回下一个数据的位置;
21.vector<int> v(first,last);
22.vector<int> v2(n,0);   
23.vector<int> v3(v2);
24.v.swap(v2);

 

 

 

 

setmultiset)的基本用法

iteratorbegin();返回指向当前集合中第一个元素的迭代器。

voidclear();清除当前集合中的所有元素。

count返回当前集合中出现的某个值的元素的数目。

boolempty();如果当前集合为空,返回true;否则返回false。

equal_range语法: pair equal_range( const key_type &key );

返回集合中与给定值相等的上下限的两个迭代器。

voiderase(iterator i );  删除i元素;

voiderase(iterator start,iterator end ); 删除从start开始到end结束的元素;

size_typeerase( const key_type &key ); 删除key值所有元素(返回被删除元素的个数)。

find:在当前集合中查找等于key值的元素,并返回指向该元素的迭代器;如果没有找到,返回指向集合最后一个元素的迭代器。

insert

iteratorinsert(iterator i, constTYPE &val ); 在迭代器i前插入val;

voidinsert(input_iterator start,input_iterator end );

将迭代器start开始到end结束返回内的元素插入到集合中;

pairinsert( constTYPE &val ); 在当前集合中插入val元素,并返回指向该元素的迭代器和一个布尔值来说明val是否成功的被插入了。(应该注意的是在集合(Sets)中不能插入两个相同的元素。)

lower_bound

返回一个指向大于或者等于key值的第一个元素的迭代器。

upper_bound

在当前集合中返回一个指向大于Key值的元素的迭代器.

Swap::voidswap( set &object );

交换当前集合和object集合中的元素。

排序

快速排序

void qs(int *arr,int left,int right)

{

     if(left>=right) return ;

     int compare=arr[left],i=left,j=right;

     while(i<j)

     {

          while (i<j&&arr[j]>compare) j--;

          arr[i]=arr[j];

          while (i<j&&arr[i]<=compare) i++;

          arr[j]=arr[i];

     }    

    arr[i]=compare;

    qs(arr,left,i-1);

     qs(arr,i+1,right);

}

归并排序

voidmerge(int *arr,int *brr,int left,int mid,int right)

{

     int i=left,j=mid+1,k=left;

     while (i<=mid&&j<=right)

           arr[i]<arr[j]?(brr[k++]=arr[i++]):(brr[k++]=arr[j++]);

     while (i<=mid) brr[k++]=arr[i++];

     while (j<=right) brr[k++]=arr[j++];

     for (i=left;i<=right;i++)arr[i]=brr[i];

}

 

voidmsort(int *arr,int *brr,int left,int right)

{

     if (left>=right) return ;

     int mid=(left+right)>>1;

     msort(arr,brr,left,mid);

     msort(arr,brr,mid+1,right);

     merge(arr,brr,left,mid,right);

}

 

 

线段树

区间取反Hdu3397

const intsize=111111;

 

struct Node

{

    int lc,mc,rc;

    int lz,mz,rz;

    int sum,lazy;

    int xr,len;

}tre[size<<2];

 

void pushup(intrt,int k)

{

    int r1=rt<<1,r2=r1|1;

    int rs=k>>1,ls=k-(k>>1);

    tre[rt].sum=tre[r1].sum+tre[r2].sum;

    if (tre[r1].lc==ls)tre[rt].lc=tre[r1].lc+tre[r2].lc;

    else tre[rt].lc=tre[r1].lc;

    if (tre[r2].rc==rs)tre[rt].rc=tre[r1].rc+tre[r2].rc;

    else tre[rt].rc=tre[r2].rc;

   tre[rt].mc=Max(tre[r1].rc+tre[r2].lc,Max(tre[r1].mc,tre[r2].mc));

    if (tre[r1].lz==ls)tre[rt].lz=tre[r1].lz+tre[r2].lz;

    else tre[rt].lz=tre[r1].lz;

    if (tre[r2].rz==rs)tre[rt].rz=tre[r1].rz+tre[r2].rz;

    else tre[rt].rz=tre[r2].rz;

    tre[rt].mz=Max(tre[r1].rz+tre[r2].lz,Max(tre[r1].mz,tre[r2].mz));

}

 

void build(intrt,int l,int r)

{

    tre[rt].lazy=-1;

    tre[rt].xr=0;

    tre[rt].len=r-l+1;

    if (l==r)

    {

        int v;

        scanf("%d",&v);

        tre[rt].lc=tre[rt].mc=tre[rt].rc=tre[rt].sum=v;

       tre[rt].lz=tre[rt].mz=tre[rt].rz=(v?0:1);

        return ;

    }

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

    build(rt<<1,l,m);

    build(rt<<1|1,m+1,r);

    pushup(rt,r-l+1);

}

 

void change(intrt)

{

    int t;

    t=tre[rt].lc;

    tre[rt].lc=tre[rt].lz;

    tre[rt].lz=t;

    t=tre[rt].mc;

    tre[rt].mc=tre[rt].mz;

    tre[rt].mz=t;

    t=tre[rt].rc;

    tre[rt].rc=tre[rt].rz;

    tre[rt].rz=t;

}

 

void Txor(int rt)

{

    if (tre[rt].lazy>=0)tre[rt].lazy=1-tre[rt].lazy;

    else tre[rt].xr^=1;

}

 

void pushdown(intrt,int k)

{

    int v=tre[rt].lazy;

    int r1=rt<<1,r2=r1|1;

    int ls=k-(k>>1),rs=k>>1;

    if (v!=-1)

    {

       tre[r1].lc=tre[r1].mc=tre[r1].rc=tre[r1].sum=(v?ls:0);

       tre[r1].lz=tre[r1].mz=tre[r1].rz=(v?0:ls);

        tre[r2].lc=tre[r2].mc=tre[r2].rc=tre[r2].sum=(v?rs:0);

       tre[r2].lz=tre[r2].mz=tre[r2].rz=(v?0:rs);

        tre[r1].xr=tre[r2].xr=0;

        tre[r1].lazy=tre[r2].lazy=tre[rt].lazy;

        tre[rt].lazy=-1;

    }

    if (tre[rt].xr)

    {

        Txor(r1);

        Txor(r2);

        tre[r1].sum=ls-tre[r1].sum;

        tre[r2].sum=rs-tre[r2].sum;

        change(r1);

        change(r2);

        tre[rt].xr=0;

    }

}

 

void update(intrt,int l,int r,int L,int R,int v)

{

    if (L<=l&&r<=R)

    {

        int k=r-l+1;

        if (v==2)

        {

            change(rt);

            tre[rt].sum=k-tre[rt].sum;

            tre[rt].xr^=1;

        }

        else

        {

           tre[rt].lc=tre[rt].mc=tre[rt].rc=tre[rt].sum=(v?k:0);

            tre[rt].lz=tre[rt].mz=tre[rt].rz=(v?0:k);

            tre[rt].lazy=v;

            tre[rt].xr=0;

        }

        return ;

    }

    if (l==r) return ;

    pushdown(rt,r-l+1);

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

    if (L<=m) update(rt<<1,l,m,L,R,v);

    if (R>m) update(rt<<1|1,m+1,r,L,R,v);

    pushup(rt,r-l+1);

}

 

Node query(intrt,int l,int r,int L,int R)

{

    Node tmp= {0};

    if (L<=l&&r<=R) returntre[rt];

    if (l==r) return tmp;

    pushdown(rt,r-l+1);

    int m=(l+r)>>1,f1=0,f2=0;

    Node r1,r2;

    if (L<=m)

    {

        r1=query(rt<<1,l,m,L,R);

        f1=1;

    }

    if (R>m)

    {

        r2=query(rt<<1|1,m+1,r,L,R);

        f2=1;

    }

    if (f1&&f2)

    {

        tmp.len=r1.len+r2.len;

        if (r1.len==r1.lc) tmp.lc=r1.lc+r2.lc;

        else tmp.lc=r1.lc;

        if (r2.rc==r2.len) tmp.rc=r1.rc+r2.rc;

        else tmp.rc=r2.rc;

       tmp.mc=Max(r1.rc+r2.lc,Max(r1.mc,r2.mc));

    }

    else if (f1) tmp=r1;

    else tmp=r2;

    return tmp;

}

 

int querysum(intrt,int l,int r,int L,int R)

{

    if (L<=l&&r<=R) return tre[rt].sum;

    if (l==r) return 0;

    pushdown(rt,r-l+1);

    int m=(l+r)>>1,res=0;

    if (L<=m)res+=querysum(rt<<1,l,m,L,R);

    if (R>m) res+=querysum(rt<<1|1,m+1,r,L,R);

    return res;

}

 

int main()

{

    int ncase,n,q,op,a,b;

    scanf("%d",&ncase);

    while (ncase--)

    {

        scanf("%d %d",&n,&q);

        n--;

        build(1,0,n);

        while (q--)

        { 

            scanf("%d %d%d",&op,&a,&b);

            if (a>b) a^=b,b^=a,a^=b;

            if (op<3) update(1,0,n,a,b,op);

            else  if (op==3)printf("%d\n",querysum(1,0,n,a,b));

            else

            {

                Node tmp=query(1,0,n,a,b);

               printf("%d\n",tmp.mc);

            }

        }

    }

    return 0;

}

Uva11983 矩形k次交

#include<cstdio>

#include<iostream>

#include<algorithm>

#define LL long long

using std::sort;

 

const int nsize=33333;

 

struct Line

{

    intlx,rx,y,f;

    Line(){}

    Line(inta,int b,int c,int d): lx(a),rx(b),y(c),f(d){}

    booloperator <(const Line &cmp) const{

        returny<cmp.y;

    }

}line[nsize<<1];

 

int X[nsize<<1],top,k;

int sum[nsize<<3][11]; //记录覆盖i次及以上的长度

int num[nsize<<3];

 

int Fin(int key,int len)

{

    intl=0,r=len;

    while(l<=r)

    {

        intm=(l+r)>>1;

        if(X[m]>key) r=m-1;

        elseif (X[m]<key) l=m+1;

        elsereturn m;

    }

    return -1;

}

 

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

{

    num[rt]=0;

   sum[rt][0]=X[r+1]-X[l];

    for (inti=1;i<=k;i++) sum[rt][i]=0;

    if (l==r)return ;

    intm=(l+r)>>1;

    build(rt<<1,l,m);

   build(rt<<1|1,m+1,r);

}

 

void PushUp(int rt,int l,int r)

{

    inti,t1=rt<<1,t2=t1|1;

    if(num[rt])

    {

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

        {

            if(num[rt]>=i) sum[rt][i]=X[r+1]-X[l];

           else if (l==r) sum[rt][i]=0;

           else sum[rt][i]=sum[t1][i-num[rt]]+sum[t2][i-num[rt]];

        }

    }

    else

    {

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

            if(l==r) sum[rt][i]=0;

           else sum[rt][i]=sum[t1][i]+sum[t2][i];

    }

}

 

void update(int rt,int l,int r,int L,int R,int v)

{

    if(L<=l&&r<=R)

    {

       num[rt]+=v;

       PushUp(rt,l,r);

        return;

    }

    intm=(l+r)>>1;

    if(L<=m) update(rt<<1,l,m,L,R,v);

    if(R>m) update(rt<<1|1,m+1,r,L,R,v);

   PushUp(rt,l,r);

}

 

int main()

{

    LL ans;

    intT,cas=0;

    intn,m,i,j,L,R;

    intx1,x2,y1,y2;

   scanf("%d",&T);

    while(T--)

    {

       scanf("%d %d",&n,&k);

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

        {

           scanf("%d %d %d %d",&x1,&y1,&x2,&y2);

           x2++,y2++;

            line[top]={x1,x2,y1,1};  X[top++]=x1;

           line[top]={x1,x2,y2,-1}; X[top++]=x2;

        }

       sort(X,X+top);

       sort(line,line+top);

        for(m=0,i=1;i<top;i++)

            if(X[i]!=X[i-1]) X[++m]=X[i];

       build(1,0,m);

        for (ans=i=0;i<top-1;i++)

        {

           L=Fin(line[i].lx,m);

           R=Fin(line[i].rx,m)-1;

            if(L<=R) update(1,0,m,L,R,line[i].f);

           ans+=1LL*sum[1][k]*(line[i+1].y-line[i].y);

        }

       printf("Case %d: %lld\n",++cas,ans);

    }

    return 0;

}

 

最大子矩阵

 poj1050最大子矩阵

int maxsum2(int *a)

{

    intsum=-INF,b=0;

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

    {

        if(b>0) b+=a[i];

        elseb=a[i];

       sum=sum>b?sum:b;

    }

    returnsum;

}

 

int maxsum(int a[size+10][size+10])

{

    inti,j,k,tmp;

    intsum=-INF;

    intb[size+10];

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

    {

        for(j=1;j<=n;j++) b[j]=0;

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

        {

           for (k=1;k<=n;k++) b[k]+=a[j][k];

           tmp=maxsum2(b);

           sum=sum>tmp?sum:tmp;

        }

    } 

    returnsum;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

字符串

函数

Sscanf函数

1、取指定长度的字符串

sscanf("123456 ", "%4s", buf);

printf("%s\n", buf);

结果为:1234

 

2、取到指定字符为止的字符串。

sscanf("123456 abcdedf", "%[^]", buf);

printf("%s\n", buf);

结果为:123456

 

3、取仅包含指定字符集的字符串。(遇到即停)

sscanf("123456abcdedfBCDEF","%[1-9a-z]", buf);

printf("%s\n", buf);

结果为:123456abcdedf

sscanf("123456abcdedfBCDEF","%[1-9A-Z]",buf);

printf("%s\n",buf);

结果为:123456

 

4、取到指定字符集为止的字符串。

sscanf("123456abcdedfBCDEF","%[^A-Z]", buf);

printf("%s\n", buf);

结果为:123456abcdedf

5、给定一个字符串iios/12DDWDFF@122,获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中

sscanf("iios/12DDWDFF@122","%*[^/]/%[^@]", buf);

printf("%s\n", buf);

结果为:12DDWDFF

 

6、s[100]=”2006:03:18-2006:04:18”

sscanf(s,"%[0-9,:]-%[0-9,:]",str1,str2);

sscanf(s,"%[^-]-%s",str1,str2);

sscanf(str1, "%d:%d:%d", &a, &b,&c);

printf("%s\n2:%s\n",str1,str2);

Sprintf函数

1.sprintf用于格式化字符串
把变量打印到字符串中,从而获得数字的字符形式,这样不需要手工转换。
例如
char c[100];int k=255;
sprintf(c,"%d",k);
//c包含"255"

2.sprintf用于进制转换
可以方便地得到变量的十六进制和八进制字符序列,再稍加处理即可得到每一位的值。
char c[100];
int k=255;
sprintf(c,"%x",k);
//c包含"ff" c[0]='f' c[1]='f'

3.sprintf用于连接字符串
方便地连接两个或者多个字符串
char buf[1024];
char a[100]="I ";
char b[100]="love ";
char c[100]="ACM."
sprintf(buf,"%s%s%s",a,b,c);
//buf 包含"I love ACM."

Strtok函数

char s[1000]; //以字符" ,."分割s字符串

while(~scanf("%s",s))

{

    char*p=strtok(s," ,.");

    while(p)

    {

       printf("%s\n",p);

       p=strtok(NULL," ,.");

    }

    char*q=s;

    inti=0;

    char*r[100];

    while(r[i++]=strtok(q," ,."))

    {

       printf("%s\n",p);

       q=NULL;

    }

 }

 

 

KMP算法

void get_next(char* T)

{

   inti=0,j=-1;

   next[0]=-1,len=strlen(T);

   while(i<len)

   {

       if(j==-1||T[i]==T[j])

       {

           ++i,++j;

           if (T[i]!=T[j]) next[i]=j;

           else next[i]=next[j];

       }

       else j=next[j];

   }

}

最小字典序字符串

int search(int len)

{

    inti=0,j=1,k=0,t;

    while(i<len&&j<len)

    {

         t=str[(i+k)%len]-str[(j+k)%len];

          if(!t) k++;

          elseif (t<0) j+=k+1,k=0;

          elsei+=k+1,k=0;  

          if(i==j) j++;

    }  

    return i;

}

计算几何

网格

#define abs(x) ((x)>0?(x):-(x))

struct point{int x,y;};

int gcd(int a,int b){

       returnb?gcd(b,a%b):a;

}

//多边形上的网格点个数

int grid_onedge(int n,point* p){

       inti,ret=0;

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

              ret+=gcd(abs(p[i].x-p[(i+1)%n].x),abs(p[i].y-p[(i+1)%n].y));

       returnret;

}

//多边形内的网格点个数

int grid_inside(int n,point* p){

       inti,ret=0;

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

              ret+=p[(i+1)%n].y*(p[i].x-p[(i+2)%n].x);

       return(abs(ret)-grid_onedge(n,p))/2+1;

}

 

几何公式

三角形:

1. 半周长P=(a+b+c)/2

2. 面积S=aHa/2=absin(C)/2=sqrt(P(P-a)(P-b)(P-c))

3. 中线Ma=sqrt(2(b^2+c^2)-a^2)/2=sqrt(b^2+c^2+2bccos(A))/2

4. 角平分线Ta=sqrt(bc((b+c)^2-a^2))/(b+c)=2bccos(A/2)/(b+c)

5. 高线Ha=bsin(C)=csin(B)=sqrt(b^2-((a^2+b^2-c^2)/(2a))^2)

6. 内切圆半径r=S/P=asin(B/2)sin(C/2)/sin((B+C)/2)

=4Rsin(A/2)sin(B/2)sin(C/2)=sqrt((P-a)(P-b)(P-c)/P)

=Ptan(A/2)tan(B/2)tan(C/2)

7. 外接圆半径R=abc/(4S)=a/(2sin(A))=b/(2sin(B))=c/(2sin(C))

8.三角形内切圆半径:r=2*s/(a+b+c)

9.三角形外接圆半径为R=(a*b*c)/(s*4);

10.s是三角形面积 a,b,c是三角形三边。11.S=√[p(p-a)(p-b)(p-c)]=1/2*a*b*sinC

12. 对角线定理 :在△ABC中,BD平分∠ABC,则AD:DC=AB:BC

四边形:

D1,D2 为对角线,M对角线中点连线,A 为对角线夹角

1.a^2+b^2+c^2+d^2=D1^2+D2^2+4M^2

2. S=D1D2sin(A)/2

(以下对圆的内接四边形)

3. ac+bd=D1D2

4.S=sqrt((P-a)(P-b)(P-c)(P-d)),P为半周长

正n边形:

R 为外接圆半径,r为内切圆半径

1. 中心角A=2PI/n

2. 内角C=(n-2)PI/n

3. 边长a=2sqrt(R^2-r^2)=2Rsin(A/2)=2rtan(A/2)

4. 面积S=nar/2=nr^2tan(A/2)=nR^2sin(A)/2=na^2/(4tan(A/2))

圆:

1. 弧长l=rA

2. 弦长a=2sqrt(2hr-h^2)=2rsin(A/2)

3. 弓形高h=r-sqrt(r^2-a^2/4)=r(1-cos(A/2))=atan(A/4)/2

4. 扇形面积S1=rl/2=r^2A/2

5. 弓形面积S2=(rl-a(r-h))/2=r^2(A-sin(A))/2

棱柱:

1. 体积V=Ah,A为底面积,h 为高

2. 侧面积S=lp,l为棱长,p 为直截面周长

3. 全面积T=S+2A

棱锥:

1. 体积V=Ah/3,A为底面积,h 为高

(以下对正棱锥)

2. 侧面积S=lp/2,l为斜高,p 为底面周长

3. 全面积T=S+A

棱台:

1. 体积V=(A1+A2+sqrt(A1A2))h/3,A1.A2为上下底面积,h 为高

(以下为正棱台)

2. 侧面积S=(p1+p2)l/2,p1.p2为上下底面周长,l 为斜高

3. 全面积T=S+A1+A2

圆柱:

1. 侧面积S=2PIrh

2. 全面积T=2PIr(h+r)

3. 体积V=PIr^2h

圆锥:

1. 母线l=sqrt(h^2+r^2)

2. 侧面积S=PIrl

3. 全面积T=PIr(l+r)

4. 体积V=PIr^2h/3

圆台:

1. 母线l=sqrt(h^2+(r1-r2)^2)

2. 侧面积S=PI(r1+r2)l

 

最近点对 Hdu1007

#include<cstring>

#include<cstdio>

#include<cmath>

#include<algorithm>

#define size 100000

struct pint

{

   double x, y;

} jeo[size];

bool cmpx(const int &a, const int &b)

{

   return jeo[a].x < jeo[b].x;

}

bool cmpy(const int &a, const int &b)

{

   return jeo[a].y < jeo[b].y;

}

double dis(int &a, int &b)

{

   return sqrt((jeo[a].x - jeo[b].x) * (jeo[a].x - jeo[b].x) + (jeo[a].y -jeo[b].y) * (jeo[a].y - jeo[b].y));

}

int n, idx[size], idy[size];

double judge(int l, int r)

{

   if (r- l == 1) return dis(idx[l], idx[r]);

   if (r- l == 2)

       return min(dis(idx[l], idx[l + 1]), min(dis(idx[l + 1], idx[l + 2]),dis(idx[l + 2], idx[l])));

   intmid = (l + r) >> 1;

   double ans = min(judge(l, mid), judge(mid + 1, r));

   intnum = 0;

   for(int i = l; i <= r; i++)

       if (jeo[idx[i]].x >= jeo[idx[mid]].x -ans && jeo[idx[i]].x <= jeo[idx[mid]].x + ans)

           idy[num++] = idx[i];

   sort(idy, idy + num, cmpy);

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

       for(int j = i + 1; j < num; j++)

       {

           if (jeo[idy[j]].y - jeo[idy[i]].y >= ans) break;

           ans = min(ans, dis(idy[j], idy[i]));

       }

   return ans;

}

int main()

{

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

   {

       for(int i = 0; i < n && scanf("%lf%lf",&jeo[i].x, &jeo[i].y); i++)

           idx[i] = i;

       sort(idx, idx + n, cmpx);

       printf("%.2f\n", judge(0, n - 1) * 0.5);

   }

   return 0;

}

叉乘法求任意多边形面积

语法:result=polygonarea(Point *polygon,int N);

参数:

*polygon

多变形顶点数组

N

多边形顶点数目

返回值:

多边形面积

注意:

 

 

支持任意多边形,凹、凸皆可

 

多边形顶点输入时按顺时针顺序排列

源程序:

 

typedefstruct {
    
double x,y;
} Point;

double polygonarea(Point *polygon,int N)
{
    
int i,j;
    
double area = 0;

    for (i=0;i<N;i++) {
        j = (i + 1) % N;
        area += polygon[i].x * polygon[j].y;
        area -= polygon[i].y * polygon[j].x;
        }

    area /= 2;
    
return(area < 0 ? -area : area);
}

 

   

 

 

 

 

 

 

 

博弈

威佐夫博弈hdu~1527/poj~1067

#include<stdio.h>

#include<math.h>

#define Q (1.0+sqrt(5))/2

int main()

{

    int a,b,k;

    while (~scanf("%d%d",&a,&b))

    {

          if (a>b) { k=a; a=b; b=k; }

          k=b-a;

          k=(int)(k*Q);

          if (k==a)printf("0\n");

          elseprintf("1\n"); 

    }

    return 0;  

}

 

Nim博弈

Hdu1907  n堆石头

#include<stdio.h>

int main()

{

    int n,t,i,s,k,cnt;

    scanf("%d",&t);

    while (t--)

    {

         scanf("%d",&n);

          s=0,cnt=0;

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

          {

             scanf("%d",&k);

              s^=k;

              if (k>1)cnt++;     

          }

          if(cnt==0&&s || cnt>=2&&s==0) printf("Brother\n");

          else  printf("John\n");

    }

    return 0;  

}

 

 

SG函数

思路

F  用一个n元组(a1, a2, …, an),来描述游戏过程中的一个局面。

F  用符号#S,表示局面S所对应的二进制数。

F  用符号$(x),表示局面(x)的下一步所有可能出现的局面的集合。

F  定义集合g(x):设$(x)={S1, S2,…, Sk},则g(x)={#S1,#S2, …, #Sk}。

F  令非负整数集为全集,集合G(x)表示集合g(x)的补集。

F  定义函数f(n):f(n)=min{G(n)},即f(n)等于集合G(n)中的最小数。

F  设局面S=(a1, a2, …,an),#S=f(a1)+f(a2)+…+f(an),采用二进制数的加法。

*#S0,则先行者有必胜策略;若#S=0,则后行者有必胜策略。

 

适用范围和限制条件:

Ø  甲乙两人取石子游戏及其类似的游戏;

Ø  每一步只能对某一堆石子进行操作;

Ø  每一步操作的限制,只与这堆石子的数目或一些常数有关;

Ø  操作在有限步内终止,并不会出现循环;

Ø  谁无法继续操作,谁就是输家。

 

Hdu 1536

#include<stdio.h>

#include<string.h>

#include<algorithm>

#include<string.h>

#include<iostream>

using namespace std;

 

const int N=1000010;

const int M=110;

 

int s[M],num,dp[N];

 

int getsg(int k)

{

    bool v[M];

    int i,temp;

    memset(v,true,sizeof(v));

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

    {

        if (k<s[i]) break;

        temp=k-s[i];

        if(temp>=0&&dp[temp]==-1) dp[temp]=getsg(temp);

        v[dp[temp]]=false;

    }

    for (i=0;;i++) if (v[i])return i;

}

 

int main()

{

    int i,j,k,t,c,d;

    while(scanf("%d",&num)&&num)

    {

          for(i=0;i<num;i++) scanf("%d",s+i);

         memset(dp,-1,sizeof(dp));

          dp[0]=0;

          sort(s,s+num); 

         scanf("%d",&t);

          for (j=0;j<t;j++)

          {

              scanf("%d",&k);

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

               {

                  scanf("%d",&d);

                   if(d>=0) dp[d]= dp[d]==-1? getsg(d):dp[d];

                   if(d>=0) c^=dp[d];

               }

              printf(c>0?"W":"L");

          }

         printf("\n");

    }

    return 0;  

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

图论

搜索

Hdu 1428优先队列广搜+记忆化搜索

#include<stdio.h>

#include<string.h>

#include<queue>

const int nsize=55;

int mark[nsize][nsize];

int map[nsize][nsize],n;

__int64 dp[nsize][nsize];

int dir[4][2]= {0,1,0,-1,1,0,-1,0};

 

struct Node

{

   int x,y,time;

   friend bool operator < (Node x1,Node x2) //优先队列,时间小的先出队

    {

       return x1.time > x2.time;

    }

};

 

bool isboundary(int x,int y)

{

   if (x<1||x>n||y<1||y>n) return false;

   return true;

}

 

void bfs()

{

   priority_queue<Node>q;

   Node cur,next;

   cur.x=n; cur.y=n;//从(n,n)开始往前找,每次找最小时间到达(n,n)

   cur.time=map[n][n];

   mark[n][n]=false;

   q.push(cur);

    while(!q.empty())

    {

       cur=q.top();

       q.pop();

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

       {

           next.x=cur.x+dir[i][0];

           next.y=cur.y+dir[i][1];

           if(isboundary(next.x,next.y)&&mark[next.x][next.y])

           {

                mark[next.x][next.y]=false;

               map[next.x][next.y]+=cur.time;//在原数组记录每个点到终点的最短时间

                next.time=map[next.x][next.y];

                q.push(next);

           }

       }

    }

}

 

__int64 dfs(int x,int y)

{

   if(dp[x][y]>0) return dp[x][y];

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

    {

       int v=x+dir[i][0];

       int u=y+dir[i][1];

       if(isboundary(u,v)&&map[x][y]>map[v][u])//保证离终点原来越近

           dp[x][y]+=dfs(v,u);

    }

   return dp[x][y];

}

 

int main()

{

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

    {

       memset(dp,0,sizeof(dp));

       memset(mark,true,sizeof(mark));

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

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

               scanf("%d",&map[i][j]);

       bfs();

       dp[n][n]=1;

       printf("%I64d\n",dfs(1,1));

    }

   return 0;

}

其他

补码

7的原码(10000111)→按位取反(11111000)(负数符号位不变)→加1(11111001)

输入输出

含空格字符串输入  while (fgets(s,MAXN,stdin)!=NULL)

数字外挂输入:

void Scan(long long&T)

{

       char C;bool F=0;

       for(;C=getchar(),C<'0'||C>'9';)if(C=='-')F=1;

       for(T=C-'0';C=getchar(),C>='0'&&C<='9';T=T*10+C-'0');

       F&&(T=-T);

}

Scan(N)  //输入正负数N

文件输入输出

1、重定向

     freopen("in","r",stdin);

    freopen("out","w",stdout);

2、非重定向

FILE *fin,*fout;

   fin=fopen("in","rb");

   fout=fopen("out","wb");

    fscanf(fin,"%d",&x);

   fprintf(fout,"%d",y);

    fclose(fin),fclose(fout);

3、#ifdef __ASD__
               freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
#endif

注意:

1.给定区间[a,b]时,考虑a和b的大小;

2.Hdu 输出用%I64d;

3.输出时,每组数据是否要换行;

4.测试数据时,重复测两次,以免初始化错误。

5.数据之和之积是否会超int;

6.根据数据范围判断用什么方法;

7.线段树注意初始化,慢慢打不要有笔误,看清题目条件,又栽了一次;

8.考虑特殊数据,极限数据;

9.拓栈#pragma comment(linker, "/STACK:1024000000,1024000000") 

int size = 256 << 20; // 256MB
    char *p = (char*)malloc(size) + size;
    __asm__("movl %0, %%esp\n" :: "r"(p) );

 

做题方法

数学

1、  打表找规律,循环节;

2、  反向思考求补集;

3、  中间过程溢出;

动态规划

1、状态转移方程

2、注意赋值顺序

3、注意初始化数组是否要初始化到最大下标

4、注意状态转移下一次循环是否要到之前的值

5、状态转移时,当前点状态对之前有影响,