读入挂:
inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; }
FASTIO
namespace fastIO { #define BUF_SIZE 1000000 //fread -> read bool IOerror = 0; inline char nc() { static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE; if(p1 == pend) { p1 = buf; pend = buf + fread(buf, 1, BUF_SIZE, stdin); if(pend == p1) { IOerror = 1; return -1; } } return *p1++; } inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; } inline void read(int &x) { char ch; while(blank(ch = nc())); if(IOerror) return; for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0'); } #undef BUF_SIZE }; using namespace fastIO;
N!的长度求法
利用斯特林公式,LL a = 0.5 * log10(2.0 * Pi * n) + n * log10(n * 1.0 / E) + 1;
给n条样子像“m”的折线,求它们能把二维平面分成的面最多是多少 (这个结论适合"z",“V”....这些折线都适合。)
n*(8*n-7)+1
转负二进制
Poj 3191 #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int ans[1000]; int main() { int a; while(~scanf("%d",&a)) { if(a==0) { printf("0\n"); continue; } int cont=0; while(a) { ans[cont++]=abs(a%(-2)); a-=abs(a%(-2)); a/=(-2); } for(int i=cont-1;i>=0;i--)printf("%d",ans[i]); printf("\n"); } }
字符串最小表示法
应用最小表示法判断两个字符串同构,只要将两个串的最小表示求出来,然后从最小表示开始比较
对于一个字符串S,求S的循环的同构字符串S’中字典序最小的一个。
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; char a[3004000]; char b[3004000]; int l; int MinimumRepresentation() { int i = 0, j = 1, k = 0, t; while(i < l && j < l && k < l) { t = b[(i + k) >= l ? i + k - l : i + k] - b[(j + k) >= l ? j + k - l : j + k]; if(!t) k++; else{ if(t > 0) i = i + k + 1; else j = j + k + 1; if(i == j) ++ j; k = 0; } } return (i < j ? i : j); } int main() { while(~scanf("%s",a)) { int n=strlen(a); l=n; a[n]=a[0]; for(int i=0;i<n;i++) { if(a[i]<=a[i+1]) b[i]=a[i+1]-a[i]; else b[i]=8-(a[i]-a[i+1]); } int tmp=MinimumRepresentation(); for(int z=0;z<n;z++) { printf("%d",b[(z+tmp)%n]); } printf("\n"); } }
字符串最大表示法求最大的下标和最小的下标
int min_express_min_pos(char *x,int n) { int i=0,j=1,k=0; while(i<n&&j<n) { k=0; while(x[i+k]==x[j+k]&&k<n)k++; if(k==n)return min(i,j); if(x[i+k]<x[j+k])i=max(i+k+1,j+1); else j=max(j+k+1,i+1); } return min(i,j); } int min_express_max_pos(char *x,int n) { int i=0,j=1,k=0; while(i<n&&j<n) { k=0; while(x[i+k]==x[j+k]&&k<n)k++; if(k==n)return n-abs(i-j)+i; if(x[i+k]<x[j+k])i=max(i+k+1,j+1); else j=max(j+k+1,i+1); } return max(i%n,j%n); }
两个乘积爆ll的处理方法
ll qmul(ll x, ll y,ll mod) //黑科技乘法 o(1)快速积 { return (x*y-(ll)(x/(long double)mod*y+0.001)*mod+mod)%mod; } ll qmul(ll x,ll y,ll mod)//俄罗斯农民乘法 { ll res = 0; while(y) { if(y&1) res = (res + x) %mod; y >>= 1; x = (x + x)%mod; } return res; }
左偏树
支持插入删除,以及合并两个堆.具有堆的性质
#include<bits/stdc++.h> using namespace std; const int maxn = 4e5+10; char op[10],str[10]; struct LT { int Hash[maxn]; int l[maxn],r[maxn]; int d[maxn],val[maxn]; int tot; void Init()//初始化 { for(int i = 0;i < maxn;++i) { d[i] = val[i] = l[i] = r[i] = Hash[i] = 0; } tot=0; } int merge(int x,int y)//合并左偏树,Logn { if(!x) return y; if(!y) return x; if(val[x] < val[y])//大顶堆 swap(x,y); r[x] = merge(r[x],y); if(d[l[x]] < d[r[x]]) swap(l[x],r[x]); d[x] += d[r[x]]+1; return x; } int init(int x)//初始化节点 { tot++; val[tot] = x; l[tot] = r[tot] = d[tot] = 0; return tot; } int insert(int x,int y)//插入新节点 { return merge(x,init(y)); } int top(int x)//取出根节点 { return val[x]; } int pop(int x)//删除根节点 { return merge(l[x],r[x]); } //删除已知节点? }T; int main() { int a,b,n; int ca=1; //下面是实现的两个堆之间的操作 while(~scanf("%d",&n),n) { T.Init(); printf("Case #%d:\n",ca++); int cnt = 0,a = -1 ,b = -1; for(int i = 1;i <= n;++i) { scanf("%s",op); if(op[1] == 'o' ) { scanf("%s",str); if(str[0]=='A') { int tmp = T.top(a); printf("%d\n",T.Hash[tmp]); a = T.pop(a); } else { int tmp = T.top(b); printf("%d\n",T.Hash[tmp]); b = T.pop(b); } } else if(op[1] == 'u') { scanf("%s",str); int x; scanf("%d",&x); if(str[0]=='A') { T.Hash[++cnt] = x; if(a==-1) a = T.init(cnt); else a = T.insert(a,cnt); } else { T.Hash[++cnt] = x; if(b==-1) b=T.init(cnt); else b=T.insert(b,cnt); } } else { char as[10],bs[10]; scanf("%s %s",as,bs); if(as[0]=='A') { if(a!=-1&&b!=-1) a=T.merge(a,b); else if(a==-1&&b!=-1) a=b; b=-1; } else { if(b!=-1&&a!=-1) b=T.merge(a,b); else if(b==-1&&a!=-1) b=a; a=-1; } } } } return 0; }