ACM模板 0.4
鉴于被穿了小鞋,马而克之。 __φ(..;)
1.高精度
1) C++版
#include<iostream>
#include<string>
#include<iomanip>
#include<algorithm>
using namespace std;
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
class BigNum
{
private:
int a[500]; //可以控制大数的位数
int len; //大数长度
public:
BigNum(){ len = 1;memset(a,0,sizeof(a)); } //构造函数
BigNum(const int); //将一个int类型的变量转化为大数
BigNum(const char*); //将一个字符串类型的变量转化为大数
BigNum(const BigNum &); //拷贝构造函数
BigNum &operator=(const BigNum &); //重载赋值运算符,大数之间进行赋值运算
friend istream& operator>>(istream&, BigNum&); //重载输入运算符
friend ostream& operator<<(ostream&, BigNum&); //重载输出运算符
BigNum operator+(const BigNum &) const; //重载加法运算符,两个大数之间的相加运算
BigNum operator-(const BigNum &) const; //重载减法运算符,两个大数之间的相减运算
BigNum operator*(const BigNum &) const; //重载乘法运算符,两个大数之间的相乘运算
BigNum operator/(const int &) const; //重载除法运算符,大数对一个整数进行相除运算
BigNum operator^(const int &) const; //大数的n次方运算
int operator%(const int &) const; //大数对一个int类型的变量进行取模运算
bool operator>(const BigNum & T)const; //大数和另一个大数的大小比较
bool operator>(const int & t)const; //大数和一个int类型的变量的大小比较
void print(); //输出大数
};
BigNum::BigNum(const int b) //将一个int类型的变量转化为大数
{
int c,d = b;
len = 0;
memset(a,0,sizeof(a));
while(d > MAXN)
{
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char*s) //将一个字符串类型的变量转化为大数
{
int t,k,index,l,i;
memset(a,0,sizeof(a));
l=strlen(s);
len=l/DLEN;
if(l%DLEN)
len++;
index=0;
for(i=l-1;i>=0;i-=DLEN)
{
t=0;
k=i-DLEN+1;
if(k<0)
k=0;
for(int j=k;j<=i;j++)
t=t*10+s[j]-'0';
a[index++]=t;
}
}
BigNum::BigNum(const BigNum & T) : len(T.len) //拷贝构造函数
{
int i;
memset(a,0,sizeof(a));
for(i = 0 ; i < len ; i++)
a[i] = T.a[i];
}
BigNum & BigNum::operator=(const BigNum & n) //重载赋值运算符,大数之间进行赋值运算
{
int i;
len = n.len;
memset(a,0,sizeof(a));
for(i = 0 ; i < len ; i++)
a[i] = n.a[i];
return *this;
}
istream& operator>>(istream & in, BigNum & b) //重载输入运算符
{
char ch[MAXSIZE*4];
int i = -1;
in>>ch;
int l=strlen(ch);
int count=0,sum=0;
for(i=l-1;i>=0;)
{
sum = 0;
int t=1;
for(int j=0;j<4&&i>=0;j++,i--,t*=10)
{
sum+=(ch[i]-'0')*t;
}
b.a[count]=sum;
count++;
}
b.len =count++;
return in;
}
ostream& operator<<(ostream& out, BigNum& b) //重载输出运算符
{
int i;
cout << b.a[b.len - 1];
for(i = b.len - 2 ; i >= 0 ; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << b.a[i];
}
return out;
}
BigNum BigNum::operator+(const BigNum & T) const //两个大数之间的相加运算
{
BigNum t(*this);
int i,big; //位数
big = T.len > len ? T.len : len;
for(i = 0 ; i < big ; i++)
{
t.a[i] +=T.a[i];
if(t.a[i] > MAXN)
{
t.a[i + 1]++;
t.a[i] -=MAXN+1;
}
}
if(t.a[big] != 0)
t.len = big + 1;
else
t.len = big;
return t;
}
BigNum BigNum::operator-(const BigNum & T) const //两个大数之间的相减运算
{
int i,j,big;
bool flag;
BigNum t1,t2;
if(*this>T)
{
t1=*this;
t2=T;
flag=0;
}
else
{
t1=T;
t2=*this;
flag=1;
}
big=t1.len;
for(i = 0 ; i < big ; i++)
{
if(t1.a[i] < t2.a[i])
{
j = i + 1;
while(t1.a[j] == 0)
j++;
t1.a[j--]--;
while(j > i)
t1.a[j--] += MAXN;
t1.a[i] += MAXN + 1 - t2.a[i];
}
else
t1.a[i] -= t2.a[i];
}
t1.len = big;
while(t1.a[len - 1] == 0 && t1.len > 1)
{
t1.len--;
big--;
}
if(flag)
t1.a[big-1]=0-t1.a[big-1];
return t1;
}
BigNum BigNum::operator*(const BigNum & T) const //两个大数之间的相乘运算
{
BigNum ret;
int i,j,up;
int temp,temp1;
for(i = 0 ; i < len ; i++)
{
up = 0;
for(j = 0 ; j < T.len ; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if(temp > MAXN)
{
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else
{
up = 0;
ret.a[i + j] = temp;
}
}
if(up != 0)
ret.a[i + j] = up;
}
ret.len = i + j;
while(ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
BigNum BigNum::operator/(const int & b) const //大数对一个整数进行相除运算
{
BigNum ret;
int i,down = 0;
for(i = len - 1 ; i >= 0 ; i--)
{
ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
}
ret.len = len;
while(ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
int BigNum::operator %(const int & b) const //大数对一个int类型的变量进行取模运算
{
int i,d=0;
for (i = len-1; i>=0; i--)
{
d = ((d * (MAXN+1))% b + a[i])% b;
}
return d;
}
BigNum BigNum::operator^(const int & n) const //大数的n次方运算
{
BigNum t,ret(1);
int i;
if(n<0)
exit(-1);
if(n==0)
return 1;
if(n==1)
return *this;
int m=n;
while(m>1)
{
t=*this;
for( i=1;i<<1<=m;i<<=1)
{
t=t*t;
}
m-=i;
ret=ret*t;
if(m==1)
ret=ret*(*this);
}
return ret;
}
bool BigNum::operator>(const BigNum & T) const //大数和另一个大数的大小比较
{
int ln;
if(len > T.len)
return true;
else if(len == T.len)
{
ln = len - 1;
while(a[ln] == T.a[ln] && ln >= 0)
ln--;
if(ln >= 0 && a[ln] > T.a[ln])
return true;
else
return false;
}
else
return false;
}
bool BigNum::operator >(const int & t) const //大数和一个int类型的变量的大小比较
{
BigNum b(t);
return *this>b;
}
void BigNum::print() //输出大数
{
int i;
cout << a[len - 1];
for(i = len - 2 ; i >= 0 ; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << a[i];
}
cout << endl;
}
int main()
{
int i,n;
BigNum x[101]; //定义大数的对象数组
x[0]=1;
for(i=1;i<101;i++)
x[i]=x[i-1]*(4*i-2)/(i+1);
while(scanf("%d",&n)==1 && n!=-1)
{
x[n].print();
}
}
2)java版
BigInteger类:
abs() 返回其值是此BigInteger的绝对值的BigInteger。
compareTo(BigInteger val) 将此BigInteger与指定的BigInteger进行比较。
divide(BigInteger val) 返回其值为 (this / val) 的BigInteger。
pow(int exponent) 返回其值为 (thisexponent) 的BigInteger。
multiply(BigInteger val) 返回其值为 (this * val) 的BigInteger。
gcd(BigInteger val) 返回一个 BigInteger,其值是 abs(this) 和 abs(val) 的最大公约数。
subtract(BigInteger val) 返回其值为 (this - val) 的 BigInteger。
BigDecimal类:
BigDecimal(String val)
将 BigDecimal 的字符串表示形式转换为 BigDecimal。
abs()
返回 BigDecimal,其值为此 BigDecimal 的绝对值,其标度为 this.scale()。
add(BigDecimal augend)
返回一个 BigDecimal,其值为 (this + augend),其标度为 max(this.scale(), augend.scale())。
compareTo(BigDecimal val)
将此 BigDecimal 与指定的 BigDecimal 比较。
divide(BigDecimal divisor, int scale, int roundingMode)
返回一个 BigDecimal,其值为 (this / divisor),其标度为指定标度。
RoundingMode
CEILING
向正无限大方向舍入的舍入模式。
DOWN
向零方向舍入的舍入模式。
FLOOR
向负无限大方向舍入的舍入模式。
HALF_DOWN
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。
HALF_EVEN
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
HALF_UP
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。
UNNECESSARY
用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。
UP
远离零方向舍入的舍入模式。
setScale(int newScale, RoundingMode roundingMode)
返回 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,以维护其总值。
subtract(BigDecimal subtrahend)
返回一个 BigDecimal,其值为 (this - subtrahend),其标度为 max(this.scale(), subtrahend.scale())。
divide(BigDecimal divisor, RoundingMode roundingMode)
返回一个 BigDecimal,其值为 (this / divisor),其标度为 this.scale()。
更多的函数请参考javaAPI文档。
示例:
import java.util.*;
import java.math.*;
public class Main{
public static void main(String[] args) {
Scanner cin = new Scanner (System.in);
int cc = cin.nextInt();
int cas = 1;
for (int i=0;i<cc;i++){
BigInteger a = cin.nextBigInteger();
BigInteger b = cin.nextBigInteger();
BigInteger c = a .add( b );
System.out.println("Case " + cas +":");
cas++;
System.out.print(a+" + " + b +" = ");
System.out.println(c);
if (i<cc-1)
System.out.println();
}
}
}
3)python版(待续)
gmpy
2.Trie
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <math.h>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const int N = 32000005;
const int M = 1000005;
const int INF = 0x3f3f3f3f;
int n,m,k;
LL a;
struct Trie
{
LL v;
int nxt[3];
void init(){
v=-1;
memset(nxt,-1,sizeof(nxt));
}
};
Trie trie[N];
int sz;
LL ans;
LL l,r;
void ini()
{
sz=1;
trie[0].init();
}
void insert(LL x,LL ip)
{
int pos=0;
for (int i=32;i>=0;i--)
{
int c;
c = (x&(1LL<<i)) ? 1 : 0;
if (trie[pos].nxt[c]==-1)
{
trie[pos].nxt[c]=sz;
trie[sz++].init();
}
pos=trie[pos].nxt[c];
}
trie[pos].v=ip;
}
void query(LL x,LL ip)
{
int pos=0;
LL res=0;
for (int i=32;i>=0;i--)
{
int c = (x&(1LL<<i)) ? 1 : 0;
if (trie[pos].nxt[c^1]!=-1)
{
pos=trie[pos].nxt[c^1];
res=(res|1)<<1;
}
else
{
pos=trie[pos].nxt[c];
res=(res|0)<<1;
}
}
res>>=1;
if (ans<=res)
{
if (ans==res)
{
if (min(ip,trie[pos].v)+1<l)
{
l=min(ip,trie[pos].v)+1;
r=max(ip,trie[pos].v);
}
}
else
{
ans=res;
l=min(ip,trie[pos].v)+1;
r=max(ip,trie[pos].v);
}
}
}
LL s[N];
int main()
{
int cc;
int cas=1;
scanf("%d",&cc);
while (cc--)
{
ans=0;
l=INF,r=0;
ini();
scanf("%d",&n);
s[0]=0;
for (int i=1;i<=n;i++)
{
scanf("%lld",&a);
s[i]=s[i-1]^a;
insert(s[i],i);
if (ans<s[i])
{
l=1;
r=i;
ans=s[i];
}
}
printf("Case #%d:\n", cas++);
for (int i=1;i<=n;i++)
query(s[i],i);
printf("%lld %lld\n", l,r);
}
return 0;
}
3.AC自动机
/*
AC + 高斯消元
骰子串匹配概率
*/
#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
const int N = 557;
const double eps = 0.0001;
int n,m, cc;
int s[N][10], d[N];
double p[N][N];
int ans[N];
struct trie
{
int sz,val[N],fail[N],tr[N][10];
void ini()
{
sz=0;
memset(tr,0,sizeof(tr));
memset(val,0,sizeof(val));
memset(fail,0,sizeof(fail));
}
int insert(int *ch)
{
int w=0;
while (*ch!=-1&&tr[w][*ch])
w=tr[w][*ch],ch++;
while (*ch!=-1)
tr[w][*ch]=++sz,ch++,w=sz;
val[w]=1;
return w;
}
void bulid()
{
queue <int> q;
for (int i=0;i<6;i++)
if (tr[0][i])
q.push(tr[0][i]);
while (!q.empty())
{
int now=q.front();
q.pop();
if (val[now])
continue;
for (int i=0;i<6;i++)
{
if (tr[now][i])
{
fail[tr[now][i]]=tr[fail[now]][i];
q.push(tr[now][i]);
}
else
tr[now][i]=tr[fail[now]][i];
}
}
}
}AC;
void gauss(int n)
{
int mi;
double h;
for (int i=1;i<=n;i++)
{
mi=i;
for (int j=i;j<=n;j++)
if (fabs(p[j][i])>fabs(p[mi][j]))
mi=j;
if (fabs(p[mi][i])<eps)
return ;
if (mi!=i)
for (int j=i;j<=n+1;j++)
swap(p[i][j],p[mi][j]);
h=p[i][i];
for (int j=i;j<=n+1;j++)
p[i][j]/=h;
for (int j=1;j<=n;j++)
if (j!=i)
{
h-=p[j][i]/p[i][i];
for (int k=1;k<=n+1;k++)
p[j][k]+=h*p[i][k];
}
}
}
int main()
{
int cas=1;
scanf("%d",&cc);
while (cc--)
{
scanf("%d%d",&n,&m);
AC.ini();
for (int i=0;i<n;i++)
{
for (int j=0;j<m;j++)
scanf("%d",&d[j]),d[j]--;
d[m]=-1;
ans[i]=AC.insert(d);
}
AC.bulid();
// for (int i=0;i<AC.sz;i++)
// {
// for (int j=0;j<6;j++)
// cout<<AC.tr[i][j]<<" ";
// cout<<endl;
// }
for (int i=0;i<AC.sz;i++)
{
d[i]=0;
for (int j=0;j<6;j++)
if (AC.tr[i][j])
d[i]++;
}
memset(p,0,sizeof(p));
for (int i=1;i<=AC.sz;i++)
p[i][i]+=1.0;
for (int i=0;i<6;i++)
if (AC.tr[0][i])
p[AC.tr[0][i]][AC.sz+1]+=1.0/d[0];
for (int i=1;i<AC.sz;i++)
{
for (int j=0;j<6;j++)
if (AC.tr[i][j])
p[AC.tr[i][j]][i]-=1.0/6.0;
if (d[i]!=6&&AC.val[i])
{
for (int j=0;j<6;j++)
if (AC.tr[0][j])
p[AC.tr[0][j]][i]-=1.0*(6-d[i])/(6.0*d[0]);
}
}
gauss(AC.sz);
for (int i=1;i<n;i++)
printf("%.6f\n",p[ans[i]][AC.sz+1]);
printf("%.6f\n",p[ans[n]][AC.sz+1]);
}
return 0;
}
4.KD_tree
/*
最近点距离
*/
#include <cstdio>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
const int N = 1000007;
const int M = 100005;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
int n,m;
int root;
int ans;
int now;
int ql,qr;
struct nd
{
int ma[2],mi[2];
int d[2];
int l,r;
}t[N<<1];
inline int getint()
{
int w=0,q=0;
char c=getchar();
while((c<'0' || c>'9') && c!='-') c=getchar();
if (c=='-') q=1, c=getchar();
while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
return q ? -w : w;
}
bool cmp(nd a,nd b)
{
if (a.d[now] == b.d[now])
return a.d[!now]<b.d[!now];
return a.d[now]<b.d[now];
}
void kd_update(int k)
{
if (t[k].l)
{
if (t[t[k].l].ma[0] > t[k].ma[0]) t[k].ma[0]=t[t[k].l].ma[0];
if (t[t[k].l].ma[1] > t[k].ma[1]) t[k].ma[1]=t[t[k].l].ma[1];
if (t[t[k].l].mi[0] < t[k].mi[0]) t[k].mi[0]=t[t[k].l].mi[0];
if (t[t[k].l].mi[1] < t[k].mi[1]) t[k].mi[1]=t[t[k].l].mi[1];
}
if (t[k].r)
{
if (t[t[k].r].ma[0] > t[k].ma[0]) t[k].ma[0]=t[t[k].r].ma[0];
if (t[t[k].r].ma[1] > t[k].ma[1]) t[k].ma[1]=t[t[k].r].ma[1];
if (t[t[k].r].mi[0] < t[k].mi[0]) t[k].mi[0]=t[t[k].r].mi[0];
if (t[t[k].r].mi[1] < t[k].mi[1]) t[k].mi[1]=t[t[k].r].mi[1];
}
}
int kd_build(int l,int r,int k)
{
int mid=(l+r)>>1;
now=k;
nth_element(t+l+1,t+mid+1,t+r+1,cmp);
if (l!=mid)
t[mid].l=kd_build(l,mid-1,!k);
if (r!=mid)
t[mid].r=kd_build(mid+1,r,!k);
t[mid].ma[0]=t[mid].mi[0]=t[mid].d[0];
t[mid].ma[1]=t[mid].mi[1]=t[mid].d[1];
kd_update(mid);
return mid;
}
int dis(int k)
{
int res=0;
if (ql<t[k].mi[0]) res+=t[k].mi[0]-ql;
if (ql>t[k].ma[0]) res+=ql-t[k].ma[0];
if (qr<t[k].mi[1]) res+=t[k].mi[1]-qr;
if (qr>t[k].ma[1]) res+=qr-t[k].ma[1];
return res;
}
void kd_query(int k)
{
int dl,dr,d0;
d0=abs(t[k].d[0]-ql)+abs(t[k].d[1]-qr);
if (d0<ans)
ans=d0;
if (t[k].l) dl=dis(t[k].l); else dl=INF;
if (t[k].r) dr=dis(t[k].r); else dr=INF;
if (dl<dr)
{
if (dl<ans)
kd_query(t[k].l);
if (dr<ans)
kd_query(t[k].r);
}
else
{
if (dr<ans)
kd_query(t[k].r);
if (dl<ans)
kd_query(t[k].l);
}
}
void kd_insert(int k)
{
int p=root,D=0;
while (1)
{
if (t[k].ma[0]>t[p].ma[0]) t[p].ma[0]=t[k].ma[0];
if (t[k].ma[1]>t[p].ma[1]) t[p].ma[1]=t[k].ma[1];
if (t[k].mi[0]<t[p].mi[0]) t[p].mi[0]=t[k].mi[0];
if (t[k].mi[1]<t[p].mi[1]) t[p].mi[1]=t[k].mi[1];
if (t[k].d[D]>=t[p].d[D])
{
if (!t[p].r)
{
t[p].r=k;
return;
}
else
p=t[p].r;
}
else
{
if (!t[p].l)
{
t[p].l=k;
return;
}
else
p=t[p].l;
}
D=!D;
}
}
int main()
{
scanf("%d%d",&n,&m);
{
for (int i=1;i<=n;i++)
scanf("%d%d",&t[i].d[0],&t[i].d[1]);
root=kd_build(1,n,0);
int x,y,z;
for (int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
if (x==1)
{
n++;
t[n].ma[0]=y;
t[n].mi[0]=y;
t[n].d[0]=y;
t[n].ma[1]=z;
t[n].mi[1]=z;
t[n].d[1]=z;
kd_insert(n);
}
else
{
ans=INF;
ql=y;
qr=z;
kd_query(root);
printf("%d\n", ans);
}
}
}
return 0;
}
5.KMP
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <math.h>
#include <vector>
#include <string.h>
#include <iomanip>
#include <set>
#include <string>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
const int N = 1000020 ;
const int MOD = 998244353 ;
const int INF = 0x3f3f3f3f;
const double Pi = acos(-1);
int n,m,p,cc;
int s[N],t[N];
int nextt[N];
int main()
{
scanf("%d",&cc);
int cas=1;
while(cc--)
{
scanf("%d%d%d",&n,&m,&p);
for (int i=0;i<n;i++)
scanf("%d",&s[i]);
for (int i=0;i<m;i++)
scanf("%d",&t[i]);
//Next Array
nextt[0]=0;
nextt[1]=0;
for (int i=1;i<m;i++)
{
int j=nextt[i];
while (j && t[i]!=t[j])
j=nextt[j];
nextt[i+1] = t[i] == t[j] ? j+1 : 0 ;
}
// Find
int ans=0;
int j=0;
for (int sta=0;sta<p;sta++)
for (int i=sta,j=0;i<n;i+=p)
{
while (j && s[i]!=t[j])
j=nextt[j];
if (s[i]==t[j])
j++;
if (j==m)
{
// printf("bug: %d\n",i-m+1); // Found!
ans++;
}
}
printf("Case #%d: %d\n",cas++,ans);
memset(nextt,0,sizeof(nextt));
memset(s,0,sizeof(s));
memset(t,0,sizeof(t));
}
return 0;
}
6.半平面交
//多边形的核
#include <stdio.h>
#include <string.h>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <math.h>
using namespace std;
const int N = 300005;
const double EXP = 1e-8;
typedef long long LL;
struct point
{
double x , y ;
}p[N];
struct line
{
point a,b;
double angle;
}l[N];
int cas,n,top,bot,order[N],ln,dq[N];
double abs(double a)
{
if (a<0)
return -a;
return a;
}
int dblcmp(double k)
{
if (abs(k)<EXP)
return 0;
return k>0?1:-1;
}
double det(point p0,point p1,point p2)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
bool cmp(int a,int b)
{
int d = dblcmp(l[a].angle-l[b].angle);
if (d==0)
return dblcmp(det(l[a].a,l[b].a,l[b].b))<0; // 逆时针输入(取左侧)时为">"
return d<0;
}
void getIntersect (line l1,line l2,point &p)
{
double d1,d2;
d1=det(l2.a,l1.b,l1.a);
d2=det(l1.b,l2.b,l1.a);
p.x=(l2.a.x*d2+l2.b.x*d1)/(d2+d1);
p.y=(l2.a.y*d2+l2.b.y*d1)/(d2+d1);
}
bool judge (line l0,line l1,line l2)
{
point p;
getIntersect(l1,l2,p);
return dblcmp(det(p,l0.a,l0.b))>0; // 逆时针输入(即取左侧)时为"<"
}
void addline(double x1,double y1,double x2,double y2)
{
l[ln].a.x=x1;
l[ln].a.y=y1;
l[ln].b.x=x2;
l[ln].b.y=y2;
l[ln].angle=atan2(y2-y1,x2-x1);
order[ln]=ln;
ln++;
}
void halfPlaneIntersection()
{
int i,j;
sort(order,order+ln,cmp);
for (i=1,j=0;i<ln;i++)
if (dblcmp(l[order[i]].angle-l[order[j]].angle)>0)
order[++j]=order[i];
ln=j+1;
dq[0]=order[0];
dq[1]=order[1];
bot=0;
top=1;
for (i=2;i<ln;i++)
{
while (bot<top&&judge(l[order[i]],l[dq[top-1]],l[dq[top]]))
top--;
while (bot<top&&judge(l[order[i]],l[dq[bot+1]],l[dq[bot]]))
bot++;
dq[++top]=order[i];
}
while (bot<top&&judge(l[order[bot]],l[dq[top-1]],l[dq[top]]))
top--;
while (bot<top&&judge(l[order[top]],l[dq[bot+1]],l[dq[bot]]))
bot++;
}
bool isCore()
{
if (top-bot>1)
return true;
return false;
}
int main ()
{
int i;
scanf ("%d",&cas);
while (cas--)
{
scanf ("%d",&n);
for (i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
for (ln=i=0;i<n-1;i++)
addline(p[i].x,p[i].y,p[i+1].x,p[i+1].y);
addline(p[i].x,p[i].y,p[0].x,p[0].y);
halfPlaneIntersection();
if (isCore())
printf("YES\n");
else
printf("NO\n");
}
return 0 ;
}
7.大素数(论文题,Meisell-Lehmer , 范围~1e11)
//Meisell-Lehmer
//G++ 218ms 43252k
#include<cstdio>
#include<cmath>
using namespace std;
#define LL long long
const int N = 5e6 + 2;
bool np[N];
int prime[N], pi[N];
int getprime()
{
int cnt = 0;
np[0] = np[1] = true;
pi[0] = pi[1] = 0;
for(int i = 2; i < N; ++i)
{
if(!np[i]) prime[++cnt] = i;
pi[i] = cnt;
for(int j = 1; j <= cnt && i * prime[j] < N; ++j)
{
np[i * prime[j]] = true;
if(i % prime[j] == 0) break;
}
}
return cnt;
}
const int M = 7;
const int PM = 2 * 3 * 5 * 7 * 11 * 13 * 17;
int phi[PM + 1][M + 1], sz[M + 1];
void init()
{
getprime();
sz[0] = 1;
for(int i = 0; i <= PM; ++i) phi[i][0] = i;
for(int i = 1; i <= M; ++i)
{
sz[i] = prime[i] * sz[i - 1];
for(int j = 1; j <= PM; ++j) phi[j][i] = phi[j][i - 1] - phi[j / prime[i]][i - 1];
}
}
int sqrt2(LL x)
{
LL r = (LL)sqrt(x - 0.1);
while(r * r <= x) ++r;
return int(r - 1);
}
int sqrt3(LL x)
{
LL r = (LL)cbrt(x - 0.1);
while(r * r * r <= x) ++r;
return int(r - 1);
}
LL getphi(LL x, int s)
{
if(s == 0) return x;
if(s <= M) return phi[x % sz[s]][s] + (x / sz[s]) * phi[sz[s]][s];
if(x <= prime[s]*prime[s]) return pi[x] - s + 1;
if(x <= prime[s]*prime[s]*prime[s] && x < N)
{
int s2x = pi[sqrt2(x)];
LL ans = pi[x] - (s2x + s - 2) * (s2x - s + 1) / 2;
for(int i = s + 1; i <= s2x; ++i) ans += pi[x / prime[i]];
return ans;
}
return getphi(x, s - 1) - getphi(x / prime[s], s - 1);
}
LL getpi(LL x)
{
if(x < N) return pi[x];
LL ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;
for(int i = pi[sqrt3(x)] + 1, ed = pi[sqrt2(x)]; i <= ed; ++i) ans -= getpi(x / prime[i]) - i + 1;
return ans;
}
LL lehmer_pi(LL x)
{
if(x < N) return pi[x];
int a = (int)lehmer_pi(sqrt2(sqrt2(x)));
int b = (int)lehmer_pi(sqrt2(x));
int c = (int)lehmer_pi(sqrt3(x));
LL sum = getphi(x, a) +(LL)(b + a - 2) * (b - a + 1) / 2;
for (int i = a + 1; i <= b; i++)
{
LL w = x / prime[i];
sum -= lehmer_pi(w);
if (i > c) continue;
LL lim = lehmer_pi(sqrt2(w));
for (int j = i; j <= lim; j++) sum -= lehmer_pi(w / prime[j]) - (j - 1);
}
return sum;
}
int main()
{
init();
LL n;
while(~scanf("%lld",&n))
{
printf("%lld\n",lehmer_pi(n));
}
return 0;
}
8.二分图最大匹配(匈牙利算法)
#include<iostream>
#include<cstdio>
#include<vector>
#include<string.h>
using namespace std;
#define M 10005
int n,k,a,b;
int match[M],used[M];
vector <int> G[M];
void add(int a,int b)
{
G[a].push_back(b);
G[b].push_back(a);
}
int dfs(int v)
{
used[v]=1;
for (int i=0;i<G[v].size();i++)
{
int u=G[v][i];
int w=match[u];
if (w<0||!used[w]&&dfs(w))
{
match[u]=v;
match[v]=u;
return 1;
}
}
return 0;
}
int bi_match()
{
int ans=0;
memset(match,-1,sizeof(match));
for (int v=0;v<n;v++)
{
memset(used,0,sizeof(used));
if (dfs(v))
ans++;
}
return ans;
}
int main()
{
scanf("%d%d",&n,&k);
int v=n*2;
for (int i=0;i<k;i++)
{
scanf("%d%d",&a,&b);
add(a-1,n+b-1);
}
printf("%d",bi_match());
return 0;
}
9.费用流
1)基于spfa的MCMF
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
#define V 10100
#define E 1000100
#define inf 99999999
using namespace std;
int vis[V];
int dist[V];
int pre[V];
struct Edge{
int u,v,c,cost,next;
}edge[E];
int head[V],cnt;
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c,int cost)
{
edge[cnt].u=u;edge[cnt].v=v;edge[cnt].cost=cost;
edge[cnt].c=c;edge[cnt].next=head[u];head[u]=cnt++;
edge[cnt].u=v;edge[cnt].v=u;edge[cnt].cost=-cost;
edge[cnt].c=0;edge[cnt].next=head[v];head[v]=cnt++;
}
bool spfa(int begin,int end){
int u,v;
queue<int> q;
for(int i=0;i<=end+2;i++){
pre[i]=-1;
vis[i]=0;
dist[i]=inf;
}
vis[begin]=1;
dist[begin]=0;
q.push(begin);
while(!q.empty()){
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next){
if(edge[i].c>0){
v=edge[i].v;
if(dist[v]>dist[u]+edge[i].cost){
dist[v]=dist[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
}
return dist[end]!=inf;
}
int MCMF(int begin,int end){
int ans=0,flow;
int flow_sum=0;
while(spfa(begin,end)){
flow=inf;
for(int i=pre[end];i!=-1;i=pre[edge[i].u])
if(edge[i].c<flow)
flow=edge[i].c;
for(int i=pre[end];i!=-1;i=pre[edge[i].u]){
edge[i].c-=flow;
edge[i^1].c+=flow;
}
ans+=dist[end];
flow_sum += flow;
}
//cout << flow_sum << endl;
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m,a,b,c;
while(scanf("%d%d",&n,&m)!=EOF){
init();
addedge(0,1,2,0);
addedge(n,n+1,2,0);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,1,c);
addedge(b,a,1,c);
}
printf("%d\n",MCMF(0,n+1));
}
return 0;
}
2)ZKW费用流(适合 稠密图 与 二分图)[效率会近高于之前10倍]
//不资瓷负权
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#define eps 1e-5
#define MAXN 222
#define MAXM 55555
#define INF 1000000007
using namespace std;
struct EDGE
{
int cost, cap, v;
int next, re;
}edge[MAXM];
int head[MAXN], e;
int vis[MAXN];
int ans, cost, src, des, n;
void init()
{
memset(head, -1, sizeof(head));
e = 0;
ans = cost = 0;
}
void add(int u, int v, int cap, int cost)
{
edge[e].v = v;
edge[e].cap = cap;
edge[e].cost = cost;
edge[e].re = e + 1;
edge[e].next = head[u];
head[u] = e++;
edge[e].v = u;
edge[e].cap = 0;
edge[e].cost = -cost;
edge[e].re = e - 1;
edge[e].next = head[v];
head[v] = e++;
}
int aug(int u, int f)
{
if(u == des)
{
ans += cost * f;
return f;
}
vis[u] = 1;
int tmp = f;
for(int i = head[u]; i != -1; i = edge[i].next)
if(edge[i].cap && !edge[i].cost && !vis[edge[i].v])
{
int delta = aug(edge[i].v, tmp < edge[i].cap ? tmp : edge[i].cap);
edge[i].cap -= delta;
edge[edge[i].re].cap += delta;
tmp -= delta;
if(!tmp) return f;
}
return f - tmp;
}
bool modlabel()
{
int delta = INF;
for(int u = 1; u <= n; u++)
if(vis[u])
for(int i = head[u]; i != -1; i = edge[i].next)
if(edge[i].cap && !vis[edge[i].v] && edge[i].cost < delta) delta = edge[i].cost;
if(delta == INF) return false;
for(int u = 1; u <= n; u++)
if(vis[u])
for(int i = head[u]; i != -1; i = edge[i].next)
edge[i].cost -= delta, edge[edge[i].re].cost += delta;
cost += delta;
return true;
}
void costflow()
{
do
{
do
{
memset(vis, 0, sizeof(vis));
}while(aug(src, INF));
}while(modlabel());
}
int nt, m;
struct point
{
int x, y;
}p[MAXN], h[MAXN];
int d[MAXN][MAXN];
char s[MAXN][MAXN];
int main()
{
while(scanf("%d%d", &m, &nt) != EOF)
{
if(m == 0 && nt == 0) break;
for(int i = 0; i < m; i++)
scanf("%s", s[i]);
int hcnt = 0, pcnt = 0;
for(int i = 0; i < m; i++)
for(int j = 0; j < nt; j++)
{
if(s[i][j] == 'H')
{
hcnt++;
h[hcnt].x = i;
h[hcnt].y = j;
}
else if(s[i][j] == 'm')
{
pcnt++;
p[pcnt].x = i;
p[pcnt].y = j;
}
}
for(int i = 1; i <= pcnt; i++)
for(int j = 1; j <= hcnt; j++)
d[i][j] = abs(p[i].x - h[j].x) + abs(p[i].y - h[j].y);
init();
n = hcnt + pcnt + 2;
src = hcnt + pcnt + 1;
des = n;
for(int i = 1; i <= pcnt; i++)
for(int j = 1; j <= hcnt; j++)
add(i, j + pcnt, 1, d[i][j]);
for(int i = 1; i <= pcnt; i++)
add(src, i, 1, 0);
for(int i = 1; i <= hcnt; i++)
add(i + pcnt, des, 1, 0);
costflow();
printf("%d\n", ans);
}
return 0;
}
10.最大流
1)Dinic
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <string>
#include <cstdio>
#include <set>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
typedef long long LL;
const int N = 305;
const int INF = (1<<20);
int n,t,a,b,c,m,k;
int map[N][N],dp[N][N];
struct edge
{
int to,cap,rev;
};
vector <edge> G[N];
int level [N],iter[N];
int used[N];
void add(int from,int to,int cap)
{
G[from].push_back((edge){to,cap,G[to].size()});
G[to].push_back((edge){from,0,G[from].size()-1});
}
void bfs (int s)
{
memset(level,-1,sizeof(level));
queue <int> que;
level[s]=0;
que.push(s);
while (!que.empty())
{
int v=que.front();
que.pop();
for (int i=0;i<G[v].size();i++)
{
edge &e= G[v][i];
if (e.cap>0&&level[e.to]<0)
{
level[e.to]=level[v]+1;
que.push(e.to);
}
}
}
}
int dfs(int v,int t,int f)
{
if (v==t)
return f;
for (int &i=iter[v];i<G[v].size();i++)
{
edge &e=G[v][i];
if (e.cap>0&&level[v]<level[e.to])
{
int d=dfs(e.to,t,min(f,e.cap));
if (d>0)
{
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int max_flow(int s,int t)
{
int flow=0;
for (;;)
{
bfs(s);
if (level[t]<0)
return flow;
memset(iter,0,sizeof(iter));
int f;
while ((f=dfs(s,t,INF))>0)
flow+=f;
}
}
void ini()
{
for (int i=0;i<=k+c+2;i++)
G[i].clear();
}
int main()
{
scanf("%d%d%d",&k,&c,&m);
{
int S=0,T=k+c+2;
n=k+c;
for (int i=1;i<=k+c;i++)
for (int j=1;j<=k+c;j++)
{
scanf("%d",&map[i][j]);
dp[i][j]=map[i][j]==0?INF:map[i][j];
}
int mi=(INF),ma=0;
for (int kk=1;kk<=n;kk++)
for (int j=1;j<=n;j++)
for (int i=1;i<=n;i++)
{
dp[i][j]=min(dp[i][j],dp[i][kk]+dp[kk][j]);
}
int l=0,r=200*n,mid;
while (l<r)
{
mid=(l+r)>>1;
ini();
for (int i=1;i<=k;i++)
{
add(S,i,m);
for (int j=k+1;j<=c+k;j++)
if (dp[i][j]<=mid)
{
add(i,j,1);
}
}
for (int j=k+1;j<=c+k;j++)
add(j,T,1);
int ans=max_flow(S,T);
if (ans==c)
r=mid;
else
l=mid+1;
}
printf("%d\n",l);
}
return 0;
}
2)SAP
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define MAXN 111
#define inf 1<<30
struct Edge{
int v,cap,next;
}edge[MAXN*MAXN];
int n,m,NE,NV;
int head[MAXN];
void Insert(int u,int v,int cap)
{
edge[NE].v=v;
edge[NE].cap=cap;
edge[NE].next=head[u];
head[u]=NE++;
edge[NE].v=u;
edge[NE].cap=0;
edge[NE].next=head[v];
head[v]=NE++;
}
int level[MAXN],gap[MAXN];
void bfs(int vt)
{
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int>que;
que.push(vt);
while(!que.empty()){
int u=que.front();
que.pop();
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-1)continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
}
int pre[MAXN],cur[MAXN];
int SAP(int vs,int vt)
{
bfs(vt);
memset(pre,-1,sizeof(pre));
memcpy(cur,head,sizeof(head));
int maxflow=0,aug=inf;
int u=pre[vs]=vs;
gap[0]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap>0&&level[u]==level[v]+1){
flag=true;
pre[v]=u;
u=v;
aug=min(aug,edge[i].cap);
if(v==vt){
maxflow+=aug;
for(u=pre[v];v!=vs;v=u,u=pre[u]){
edge[cur[u]].cap-=aug;
edge[cur[u]^1].cap+=aug;
}
aug=inf;
}
break;
}
}
if(flag)continue;
int minlevel=NV;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap>0&&level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0)break;
level[u]=minlevel+1;
gap[level[u]]++;
u=pre[u];
}
return maxflow;
}
bool map[MAXN][MAXN];
void Build()
{
NE=0;
memset(head,-1,sizeof(head));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==j)
Insert(i,i+n,1);
else if(map[i][j])
Insert(i+n,j,inf);
}
}
}
int main()
{
// freopen("1.txt","r",stdin);
int u,v,ans;
while(~scanf("%d%d",&n,&m)){
NV=2*n;
memset(map,false,sizeof(map));
while(m--){
scanf(" (%d,%d)",&u,&v);
map[u][v]=map[v][u]=true;
}
ans=n;
for(int vs=0;vs<n;vs++){
for(int vt=vs+1;vt<n;vt++){
Build();
int tp=SAP(vs+n,vt);
//cout<<"bug: "<<tp<<endl;
ans=min(ans,tp);
}
}
//if(ans>=n)ans=n;
printf("%d\n",ans);
}
return 0;
}
11.后缀数组
1)倍增法
//包含c的不重复子串个数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int MAXN=100010;
int sa[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];
int Rank[MAXN],height[MAXN];
/*
sa[1~~n]为有效值 sa[i]=a则代表排在第 i 位的是第a个后缀。 a属于[0~~n-1]
rank[0~~n-1]是有效值 rank[i]=b则代表第 i 个后缀排在第b位 b属于[1~~n]
height[2~~n]是有效值 height[i]=c 则代表排在第 i 位的后缀和排在第i-1的后缀的最长前缀长度是c。
*/
void construct_sa(int s[],int n,int m){
int i,j,p,*x=t1,*y=t2;
for(i=0;i<m;i++)c[i]=0;
for(i=0;i<n;i++)c[x[i]=s[i]]++;
for(i=1;i<m;i++)c[i]+=c[i-1];
for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
for(j=1;j<=n;j<<=1){
p=0;
for(i=n-j;i<n;i++)y[p++]=i;
for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
for(i=0;i<m;i++)c[i]=0;
for(i=0;i<n;i++)c[x[y[i]]]++;
for(i=1;i<m;i++)c[i]+=c[i-1];
for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(i=1;i<n;i++)
x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
if(p>=n)break;
m=p;
}
}
void construct_lcp(int s[],int n){
int k=0;
for(int i=0;i<=n;i++) Rank[sa[i]]=i;
for(int i=0;i<n;i++){
if(k)k--;
int j=sa[Rank[i]-1];
while(s[i+k]==s[j+k])k++;
height[Rank[i]]=k;
}
}
int fvis[MAXN],pr[MAXN],s[MAXN];
char str[MAXN];
int main(){
int T,cas=1;
char ch[10];
scanf("%d",&T);
while(T--){
scanf("%s",ch);
scanf("%s",str);
int n=strlen(str),flag=0,fpr;
for(int i=0;i<=n;i++) s[i]=str[i];
memset(fvis,0,sizeof(fvis));
memset(pr,0,sizeof(pr));
for(int i=n-1;i>=0;i--){
if(str[i]==ch[0]){
flag=1;fpr=i;
}
if(flag) fvis[i]=1,pr[i]=fpr;
}
ll ans=0;
construct_sa(s,n+1,128);
construct_lcp(s,n);
for(int i=0;i<=n;i++){
if(fvis[sa[i]]) ans=ans+n-max((sa[i]+height[i]),pr[sa[i]]);
}
printf("Case #%d: %I64d\n",cas++,ans);
}
return 0;
}
12.计算几何通用类
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
#define MAX 111116
#define eps 1e-7
using namespace std;
int sgn(const double &x){ return x < -eps? -1 : (x > eps);}
inline double sqr(const double &x){ return x * x;}
inline int gcd(int a, int b){ return !b? a: gcd(b, a % b);}
struct Point
{
double x, y;
Point(){}
Point(const double &x, const double &y):x(x), y(y){}
Point operator -(const Point &a)const{ return Point(x - a.x, y - a.y); }
Point operator +(const Point &a)const{ return Point(x + a.x, y + a.y); }
Point operator * (const double &a)const{ return Point(x * a, y * a); }
Point operator / (const double &a)const{ return Point(x / a, y / a); }
friend double det(const Point &a, const Point &b){ return a.x * b.y - a.y * b.x;}
friend double dot(const Point &a, const Point &b){ return a.x * b.x + a.y * b.y;}
friend double dist(const Point &a, const Point &b){ return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
void in(){ scanf("%lf %lf", &x, &y); }
void out(){ printf("%.2f %.2f\n", x, y); }
};
struct Line
{
Point s, t;
Line() {}
Line(const Point &s, const Point &t):s(s), t(t) {}
void in() { s.in(),t.in(); }
double pointDistLine(const Point &p)
{
if(sgn(dot(t - s, p - s)) < 0)return dist(p, s);
if(sgn(dot( s - t, p - t)) < 0)return dist(p, t);
return fabs(det(t - s, p - s)) / dist(s, t);
}
bool pointOnLine(const Point &p)
{
return sgn(det(t - s, p - s)) == 0 && sgn(dot(s - p, t - p)) <= 0;
}
};
struct Poly //多边形类
{
vector<Point>a;
void in(const int &r)
{
a.resize(r);
for(int i = 0; i < r; i++) a[i].in();
}
//计算多边形的周长
double perimeter()
{
double sum=0;
int n=a.size();
for(int i=0;i<n;i++) sum+=dist(a[i],a[(i+1)%n]);
return sum;
}
//计算多边形的面积
double getDArea()
{
int n = a.size();
double ans = 0;
for(int i = 0; i < n; i++) ans += det(a[i], a[(i + 1)%n]);
return ans / 2;
}
//计算多边形的重心坐标
Point getMassCenter()
{
Point center(0, 0);
if(sgn(getDArea())==0) return center; //面积为0情况,当然这题说了面积不可能为0可不写
int n = a.size();
for(int i = 0; i < n; i++)
center =center + (a[i] + a[(i + 1) % n]) * det(a[i], a[(i + 1) % n]);
return center / getDArea() / 6;
}
//计算点t是否在多边形内,返回0指在外,1指在内,2指在边界上
int pointOnline(Point t)
{
int num=0,i,d1,d2,k,n=a.size();
for(i=0;i<n;i++)
{
Line line=Line(a[i],a[(i+1)%n]);
if(line.pointOnLine(t)) return 2;
k=sgn(det(a[(i+1)%n]-a[i],t-a[i]));
d1=sgn(a[i].y-t.y);
d2=sgn(a[(i+1)%n].y-t.y);
if(k>0&&d1<=0&&d2>0) num++;
if(k<0&&d2<=0&&d1>0) num--;
}
return num!=0;
}
}poly;
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
poly.in(n);
poly.getMassCenter().out();
}
return 0;
}
13.矩阵快速幂
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 200005
#define MAXN 1000005
#define maxnode 205
#define sigma_size 26
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair<int,int>
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-4;
const LL mod = 1e9+7;
const ull mx = 133333331;
struct Matrix{
int n;
LL maze[maxnode][maxnode];
void init(int n)
{
this->n = n;
mem(maze,0);
}
Matrix operator * (Matrix &rhs)
{
Matrix m;
m.init(n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
m.maze[i][j] = (m.maze[i][j] + maze[i][k] * rhs.maze[k][j])%mod;
return m;
}
};
int k;
LL qpow(Matrix a,int n)
{
Matrix ans;
ans.init(a.n);
for(int i=0;i<ans.n;i++)
ans.maze[i][i] = 1;
while(n)
{
if(n&1) ans = ans * a;
a = a*a;
n >>= 1;
}
LL sum=0;
for (int i=0;i<ans.n;i++)
{
sum+=ans.maze[i][0];
sum%=mod;
}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d%d",&n,&m,&k);
Matrix A;
A.init(m+1);
for (int i=0;i<=m;i++)
A.maze[0][i]=k*k-k;
for (int i=0;i<=m;i++)
A.maze[i+1][i]=k;
LL ans=qpow(A,n);
A.init(m);
for (int i=0;i<m;i++)
A.maze[0][i]=k*k-k;
for (int i=0;i<m;i++)
A.maze[i+1][i]=k;
ans=(ans-qpow(A,n)+mod)%mod;
printf("%lld\n",ans);
}
return 0;
}
14.快速傅里叶变换 (FFT)
/*
algorithm : High-Precision FFT
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 200005
#define pi acos(-1.0) // PI值
using namespace std;
struct complex
{
double r,i;
complex(double real=0.0,double image=0.0){
r=real; i=image;
}
// 以下为三种虚数运算的定义
complex operator + (const complex o){
return complex(r+o.r,i+o.i);
}
complex operator - (const complex o){
return complex(r-o.r,i-o.i);
}
complex operator * (const complex o){
return complex(r*o.r-i*o.i,r*o.i+i*o.r);
}
}x1[N],x2[N];
char a[N/2],b[N/2];
int sum[N]; // 结果存在sum里
void brc(complex *y,int l) // 二进制平摊反转置换 O(logn)
{
register int i,j,k;
for(i=1,j=l/2;i<l-1;i++)
{
if(i<j) swap(y[i],y[j]); // 交换互为下标反转的元素
// i<j保证只交换一次
k=l/2;
while(j>=k) // 由最高位检索,遇1变0,遇0变1,跳出
{
j-=k;
k/=2;
}
if(j<k) j+=k;
}
}
void fft(complex *y,int l,double on) // FFT O(nlogn)
// 其中on==1时为DFT,on==-1为IDFT
{
register int h,i,j,k;
complex u,t;
brc(y,l); // 调用反转置换
for(h=2;h<=l;h<<=1) // 控制层数
{
// 初始化单位复根
complex wn(cos(on*2*pi/h),sin(on*2*pi/h));
for(j=0;j<l;j+=h) // 控制起始下标
{
complex w(1,0); // 初始化螺旋因子
for(k=j;k<j+h/2;k++) // 配对
{
u=y[k];
t=w*y[k+h/2];
y[k]=u+t;
y[k+h/2]=u-t;
w=w*wn; // 更新螺旋因子
} // 据说上面的操作叫蝴蝶操作…
}
}
if(on==-1) for(i=0;i<l;i++) y[i].r/=l; // IDFT
}
int main(void)
{
int l1,l2,l;
register int i;
while(scanf("%s%s",a,b)!=EOF)
{
l1=strlen(a);
l2=strlen(b);
l=1;
while(l<l1*2 || l<l2*2) l<<=1; // 将次数界变成2^n
// 配合二分与反转置换
for(i=0;i<l1;i++) // 倒置存入
{
x1[i].r=a[l1-i-1]-'0';
x1[i].i=0.0;
}
for(;i<l;i++) x1[i].r=x1[i].i=0.0;
// 将多余次数界初始化为0
for(i=0;i<l2;i++)
{
x2[i].r=b[l2-i-1]-'0';
x2[i].i=0.0;
}
for(;i<l;i++) x2[i].r=x2[i].i=0.0;
fft(x1,l,1); // DFT(a)
fft(x2,l,1); // DFT(b)
for(i=0;i<l;i++) x1[i]=x1[i]*x2[i]; // 点乘结果存入a
fft(x1,l,-1); // IDFT(a*b)
for(i=0;i<l;i++) sum[i]=x1[i].r+0.5; // 四舍五入
for(i=0;i<l;i++) // 进位
{
sum[i+1]+=sum[i]/10;
sum[i]%=10;
}
l=l1+l2-1;
while(sum[l]<=0 && l>0) l--; // 检索最高位
for(i=l;i>=0;i--) putchar(sum[i]+'0'); // 倒序输出
putchar('\n');
}
return 0;
}
15.快速数论变换 NTT
/*
1.快速傅里叶变换适用于所有复数,但是存在精度问题。
2.数论变换只能用于整数,但是速度会更快,可有准确求出卷积。
3.数组常开n的4倍。
*/
//NTT
const long long P = 50000000001507329LL; //190734863287 * 2 ^ 18 + 1
const int G = 3;//P的原根
long long wn[25];//此时应该大于18
long long mul(long long x, long long y) {
return (x*y - (long long)(x / (long double)P*y + 1e-3) * P + P) % P;
}//保证求余时两个数都是正的,处理精度问题
long long qpow(long long x, long long k) {
long long ret = 1;
while(k) {
if(k & 1) ret = mul(ret, x);
k >>= 1;
x = mul(x, x);
}
return ret;
}
void getwn() {
for(int i = 1; i <= 18; ++i) {
int t = 1 << i;
wn[i] = qpow(G, (P - 1)/t);
}
}
int len;
void change(long long y[], int len) {
for(int i = 1, j = len/2; i < len - 1; ++i) {
if(i < j) swap(y[i], y[j]);
int k = len/2;
while(j >= k) {
j -= k;
k /= 2;
}
j += k;
}
}
void NTT(long long y[], int on) {
change(y, len);
int id = 0;
for(int h = 2; h <= len; h <<= 1) {
++id;
for(int j = 0; j < len; j += h) {
long long w = 1;
for(int k = j; k < j + h / 2; ++k) {
long long u = y[k];
long long t = mul(y[k+h/2], w);
y[k] = u + t;
if(y[k] >= P) y[k] -= P;
y[k+h/2] = u - t + P;
if(y[k+h/2] >= P) y[k+h/2] -= P;
w = mul(w, wn[id]);
}
}
}
if(on == -1) {
for(int i = 1; i < len / 2; ++i) swap(y[i], y[len-i]);
long long inv = qpow(len, P - 2);
for(int i = 0; i < len; ++i)
y[i] = mul(y[i], inv);
}
}
void Convolution(long long A[],long long B[],int n){
for(len=1; len<(n<<1); len<<=1);
for(int i=n; i<len; ++i){
A[i]=B[i]=0;
}
NTT(A,1); NTT(B,1);
for(int i=0; i<len; ++i){
A[i]=mul(A[i],B[i]);
}
NTT(A,-1);
}
16.读入外挂
inline int getint()
{
int w=0,q=0;
char c=getchar();
while((c<'0' || c>'9') && c!='-') c=getchar();
if (c=='-') q=1, c=getchar();
while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
return q ? -w : w;
}