简单的模板整理(待续)
来源:互联网 发布:广数g92车英制螺纹编程 编辑:程序博客网 时间:2024/06/15 10:01
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 4class 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 longconst 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 10005int 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 99999999using 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<<30struct 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-7using 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倍。*///NTTconst long long P = 50000000001507329LL; //190734863287 * 2 ^ 18 + 1const int G = 3;//P的原根long long wn[25];//此时应该大于18long 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;}
我可是有底线的(  ̄▽ ̄)((≧︶≦)
- 简单的模板整理(待续)
- 部分简单数论模板(未完待续)
- 关于虚函数的整理(待续)
- CS229的简单梳理(待续)
- 简单的SQL常识(待续)
- IE与FireFox的兼容性问题(JoeCom整理--未完待续)
- dbcp数据源的配置(tomcat)整理待续
- 关于抽象类的整理(未完待续)
- Matlab中常见的错误整理(待续)
- 图的色数问题整理(未完待续......)
- maven 自己的整理的笔记 - 待续
- 几个简单的HBase的Java程序(待续)
- 问题简单汇总(待续)
- [Oracle]学习Oracle数据库的简单笔记(未完待续)
- LIST_ENTRY的介绍以及简单实用(未完待续)
- CMDB客户端检测的简单实现 (待续)
- php 简单函数整理 未完待续,长期更新.....
- android开发 日常常用整理(待续)
- openssl升级
- 算术表达式求解——堆栈的应用
- js程序 下拉框功能,当选择大学下拉框时,隐藏下拉框,将其对应的值,展示到span标签中
- db64封装函数,可以直接用。
- LeetCode--ZigZag Conversion
- 简单的模板整理(待续)
- 十大热门行业公布 成都仍是跳槽首选
- uboot启动过程(代码流程)
- Eclipse Memory Analyzer
- haproxy+keepalived的集成
- NPM配置问题
- 欢迎使用CSDN-markdown编辑器
- xml-在程序中写xml并将内存中的xml保存至文件中
- java学习笔记-类, 面向对象特性,包机制