杂乱的东西


读入挂:

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;
}




猜你喜欢

转载自blog.csdn.net/howardemily/article/details/77783231
今日推荐