杂(模板)
来源:互联网 发布:js模仿php获取参数 编辑:程序博客网 时间:2024/05/18 14:45
二维map这么开
读入优化
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;}
四国以
printf("%*d",length+1,a[i][j]); //其中*号是位数 对应length是对应位数的数据 +1是数值之前的空格占一位
利用斯特林公式,LL a = 0.5 * log10(2.0 * Pi * n) + n * log10(n * 1.0 / E) + 1;
Wiki链接
求逆序对数
int sum[N];#define lowbit(x) (x&-x)void update(int index,int val){for(int i=index;i<N;i+=lowbit(i))sum[i]+=val;}int getSum(int index){int ans=0;for(int i=index;i;i-=lowbit(i))ans+=sum[i];return ans;}int a[N],b[N];int findi(int *a,int len,int n){ int l = 1,r = len,mid,ans=-1; while(l<=r){ mid = (l+r)>>1; if(a[mid]>=n){ ans = mid; r=mid-1; } else l=mid+1; } return ans;}int main(){ int n; while(~scanf("%d",&n)){ LL ans = 0; Rep(i,1,n) a[i]=read(),sum[i]=0,b[i]=a[i]; sort(b+1,b+n+1); int len = unique(b+1,b+n+1)-b-1; Per(i,n,1){ int id = findi(b,len,a[i]); ans+=getSum(id); update(id,1); } printf("%d\n",ans); } return 0;}
最长上升子序列相关
#include <iostream>#include <algorithm>#include <cmath>#include <cstdio>#include <cstring>using namespace std;typedef long long int LL ;const LL MOD = 1e9+7;const LL INF = 0xffffffff;const int N = 1e5+7;int a[N];int b[N]; //为以a[i]为结尾的最长上升子序列的长度int c[N];int findi(int *a,int len,int n)//若返回值为x,则a[x]>=n>a[x-1]{ int left=0,right=len,mid=(left+right)/2; while(left<=right){ if(n>a[mid]) left=mid+1; else if(n<a[mid]) right=mid-1; else return mid; mid=(left+right)/2; } return left;}void filli(int *a,int n){ for(int i=0;i<=n;i++) a[i]=1e9+7;}int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); filli(c,n+1); int i,j; for(i=0;i<n;i++) scanf("%d",&a[i]); c[0]=-1; c[1]=a[0]; b[0]=1; for(i=1;i<n;i++){ j=findi(c,n+1,a[i]); c[j]=a[i]; b[i]=j; } printf("%d",b[0]); for(i=1;i<n;i++) printf(" %d",b[i]); puts(""); } return 0;}
单调队列 专题链接
1.单调队列:在一个双端对列中维护最后解的方法;
一般适用于:
在一个动态的范围内 对于一个限定长度的子区间进行处理最优解的过程
[解决浮动窗口的最优解]
注意: 顾名思义 一定要保证队列中元素的单调性
int deq[] ;//队列实体int p[] ;//维护下标int head =1,tail = 0; //用于维护双端对列的左右值、。p[0]=p[++r]=0;//其实P[0] 是没有用的。。while(l<=r && p[l] < i-k) l++; //不满足子区间长度的需要出队列tem = 当前最优解 ; // 一定要在更新之前计算 否则结果可能因为负值or other 出现错误if( tem > mx ) mx=tem,以及需要进行的操作 ;while(l<=r && 最优解需要的条件) r--;//更新最优解p[++r]=i;
康拓展开 转自
康托展开
练习题目:NYOJ 139
>康托展开的公式是 X=an*(n-1)!+an-1*(n-2)!+…+ai*(i-1)!+…+a2*1!+a1*0! 其中,ai为当前未出现的元素中是排在第几个(从0开始)。
>这个公式可能看着让人头大,最好举个例子来说明一下。例如,有一个数组 s = [“A”, “B”, “C”, “D”],它的一个排列 s1 = [“D”, “B”, “A”, “C”],现在要把 s1 映射成 X。n 指的是数组的长度,也就是4,所以
X(s1) = a4*3! + a3*2! + a2*1! + a1*0!
关键问题是 a4、a3、a2 和 a1 等于啥?
a4 = “D” 这个元素在子数组 [“D”, “B”, “A”, “C”] 中是第几大的元素。”A”是第0大的元素,”B”是第1大的元素,”C” 是第2大的元素,”D”是第3大的元素,所以 a4 = 3。
a3 = “B” 这个元素在子数组 [“B”, “A”, “C”] 中是第几大的元素。”A”是第0大的元素,”B”是第1大的元素,”C” 是第2大的元素,所以 a3 = 1。
a2 = “A” 这个元素在子数组 [“A”, “C”] 中是第几大的元素。”A”是第0大的元素,”C”是第1大的元素,所以 a2 = 0。
a1 = “C” 这个元素在子数组 [“C”] 中是第几大的元素。”C” 是第0大的元素,所以 a1 = 0。(因为子数组只有1个元素,所以a1总是为0)
所以,X(s1) = 3*3! + 1*2! + 0*1! + 0*0! = 20A B C | 0
A C B | 1
B A C | 2
B C A | 3
C A B | 4
C B A | 5
通过康托逆展开生成全排列
练习题目:HDU 1027
如果已知 s = [“A”, “B”, “C”, “D”],X(s1) = 20,能否推出 s1 = [“D”, “B”, “A”, “C”] 呢?
因为已知 X(s1) = a4*3! + a3*2! + a2*1! + a1*0! = 20,所以问题变成由 20 能否唯一地映射出一组 a4、a3、a2、a1?如果不考虑 ai 的取值范围,有
3*3! + 1*2! + 0*1! + 0*0! = 20
2*3! + 4*2! + 0*1! + 0*0! = 20
1*3! + 7*2! + 0*1! + 0*0! = 20
0*3! + 10*2! + 0*1! + 0*0! = 20
0*3! + 0*2! + 20*1! + 0*0! = 20
等等。但是满足 0 <= ai <= n-1 的只有第一组。可以使用辗转相除的方法得到 ai,如下图所示:
知道了a4、a3、a2、a1的值,就可以知道s1[0] 是子数组[“A”, “B”, “C”, “D”]中第3大的元素 “D”,s1[1] 是子数组 [“A”, “B”, “C”] 中第1大的元素”B”,s1[2] 是子数组 [“A”, “C”] 中第0大的元素”A”,s[3] 是子数组 [“C”] 中第0大的元素”C”,所以s1 = [“D”, “B”, “A”, “C”]。
这样我们就能写出一个函数 Permutation3(),它可以返回 s 的第 m 个排列。
#include<iostream> #include<algorithm> #include<vector> #include<cstdlib> using namespace std; class cantor{ public: int n;//字符串的长度 string s; int pos;//字符串在全排列中的字典位置,从0开始 vector<int>num;//所有的字符 cantor(string s):s(s){n=s.size();} cantor(int n,int pos):n(n),pos(pos){ int i; for(i=0;i<n;i++) num.push_back(i); } int fac(int); void encode(); void decode(); }; int cantor::fac(int num){ if(num==0) return 1; else return num*fac(num-1); } void cantor::encode(){ int i,j,count; vector<int>vec(n); for(i=0;i<n;i++){ count=0; for(j=i;j<n;j++) if(s[i]>s[j]) count++; vec[n-i-1]=count; } pos=0; for(i=0;i<s.size();i++) pos+=vec[i]*fac(i); } void cantor::decode(){ int i; div_t divresult; for(i=n-1;i>=0;i--){ divresult=div(pos,fac(i));求余数与除数 s.push_back(num[divresult.quot]+'0'); num.erase(num.begin()+divresult.quot); pos=divresult.rem; } } int main(){ cantor test(4,2); test.decode(); cout<<test.s<<endl; }/****************************************////这是我自己撸的 比上面的容易看的多int jiecheng[10] = {1,1,2,6,24,120,720,5040,40320,362880};int a[10],b[10];int Cantor_expansion(int a[],int len){ int x=0; for(int i=0; i<len; i++) for(int j=i+1; j<len; j++) if(a[j]<a[i]) x+=jiecheng[len-1-i]; return x ;}bool h[len+5];//len就是序列长度void Cantor_inexpansion(int x,int len){ memset(h,0,sizeof(h)); int ind ,tem; for(int i=0; i<len; i++) { ind = 0; tem = x/jiecheng[len-1-i]; x %= jiecheng[len-1-i]; for(int j=1; j<=len; j++) { if(h[j]) continue; if(ind==tem) { a[i]=j; break; } ind++; } h[a[i]]=1; } return ;}
双调欧几里得旅行商问题
算法介绍
http://blog.csdn.net/zchahaha/article/details/51058738
http://www.mamicode.com/info-detail-523965.html
int dp[N][N]; //dp[i][j]为i点到1点,再从1点到j点的最短距离,int d[N][N]; //d[i][j] 为 i->j的距离struct point{ int x, y;}a[N];int dis(int i, int j){ int p,q; if(a[i].y>a[j].y) q=(360+a[j].y-a[i].y)%360; else q=(360+a[i].y-a[j].y)%360; p=abs(a[i].y-a[j].y)>q?q:abs(a[i].y-a[j].y); return (abs(a[i].x-a[j].x)*400+p);}int main(){ int _,n; scanf("%d",&_); while(_--){ scanf("%d", &n); a[1].x=0,a[1].y=0; for(int i = 2; i <= n+1; i++) scanf("%d %d", &a[i].x, &a[i].y); for(int i = 1; i <= n+1; i++) for(int j = 1; j <= n+1; j++) d[i][j] = dis(i, j); dp[1][2] = d[1][2]; for(int i = 3; i <= n+1; i++){ for(int j = 1; j < i-1; j++) dp[j][i] = dp[j][i-1] + d[i-1][i]; dp[i-1][i] = 999999999; for(int j = 1; j < i-1; j++){ int sum = dp[j][i-1] + d[j][i]; if(dp[i-1][i] > sum) dp[i-1][i] = sum; } } dp[n+1][n+1] = dp[n][n+1] + d[n][n+1]; printf("%d\n", dp[n+1][n+1]+10*n); } return 0;}
线性基
线性基讲义
基:在线性代数中,基(也称为基底)是描述、刻画向量空间的基本工具。向量空间的基是它的一个特殊的子集,基的元素称为基向量。向量空间中任意一个元素,都可以唯一地表示成基向量的线性组合。如果基中元素个数有限,就称向量空间为有限维向量空间,将元素的个数称作向量空间的维数。
同样的,线性基是一种特殊的基,它通常会在异或运算中出现,它的意义是:通过原集合S的某一个最小子集S1使得S1内元素相互异或得到的值域与原集合S相互异或得到的值域相同。
性质
1. 线性基能相互异或得到原集合的所有相互异或得到的值。
2. 线性基是满足性质1的最小的集合
3. 线性基没有异或和为0的子集。
求线性基.
void Guass(){ for (int i=1;i<=sz;i++) for (int j=63;j>=0;j--) if ((A[i]>>j)&1){ if (!P[j]) {P[j]=A[i]; break;} else A[i]^=P[j]; } for (int j=0;j<=63;j++) if (P[j]) r++;}r为极大无关组的大小
算术表达式 计算
中缀表达式
中心思想就是用两个栈来维护,一个用来存储符号,另一个用来存储数值.
/***author: tabris time : 2017/2/17 17:03这是在int范围内的整数计算的模板。包括+-*/() 六个符号*/char a[111];stack<int >num;//数值栈stack<char >ch;//符号栈//这个函数只接收+-号,+-号等级最低,运算符栈中除了括号外 都可以取出运算void js1(){ int num1,num2; //从运算符栈中取一个运算符 对数值栈顶和次顶元素进行运算 while(ch.top()!='('){ num1 = num.top(); num.pop(); num2 = num.top(); num.pop(); if(ch.top()=='+') num2+=num1; if(ch.top()=='-') num2-=num1; if(ch.top()=='*') num2*=num1; if(ch.top()=='/') num2/=num1; num.push(num2);//将计算结果入数值栈 ch.pop();//删除已经用过的符号 }}//只接收*/运算符void js2() { int num1,num2; //栈中只有*/优先级大于*/ while (ch.top()=='*' || ch.top()=='/') { num1 = num.top(); num.pop(); num2 = num.top(); num.pop(); if(ch.top()=='*') num2*=num1; if(ch.top()=='/') num2/=num1; num.push(num2);ch.pop(); }}int solve(char *str){ while(!ch.empty()) ch.pop(); while(!num.empty()) num.pop(); int len = strlen(str); int tem=0; bool flag = false; ch.push('('); strcat(str,"."); for(int i=0;i<=len;i++){ if(str[i]>='0'&&str[i]<='9'){ flag = true; tem=(tem<<3)+(tem<<1)+str[i]-'0'; continue; } if(flag){ num.push(tem); tem = 0; flag = false; } if(str[i]=='+'||str[i]=='-'){ js1(); ch.push(str[i]); } else if(str[i]=='*'||str[i]=='/'){ js2(); ch.push(str[i]); } else if(str[i]=='('){ ch.push(str[i]); } else if(str[i]==')'){ js1(); ch.pop(); } else if(str[i]=='.'){ js1(); ch.pop(); } } return num.top();}int main(){ while(~scanf("%s",a))printf("%d\n",solve(a)); return 0;}
后缀表达式
后缀表达式也叫逆波兰表达式
参阅这里
#include<iostream>#include<stack>#include<stdio.h>#include<string.h>using namespace std;int main(){ string PostArray; int len,i,a,b; while(cin>>PostArray){ stack<int> Stack; len = PostArray.length(); for(i = 0;i < len;i++){ //跳过空格 if(PostArray[i] == ' '){ continue; } //如果是数字则入栈 if(PostArray[i] >= '0' && PostArray[i] <= '9'){ Stack.push(PostArray[i] - '0'); } //如果是字符则从栈读出两个数进行运算 else{ //算数a出栈 a = Stack.top(); Stack.pop(); //算法b出栈 b = Stack.top(); Stack.pop(); //进行运算(+ - * /) if(PostArray[i] == '+'){ Stack.push(a + b); } else if(PostArray[i] == '-'){ Stack.push(a - b); } else if(PostArray[i] == '*'){ Stack.push(a * b); } else if(PostArray[i] == '/'){ Stack.push(a / b); } } }//for printf("%d\n",Stack.top()); }//while return 0;}
多项式取模
对于两个多项式,求多项式的gcd,要求首项次数为1,多项式中的运算都%n
#include <bits/stdc++.h>using namespace std;#define INF (~(1<<31))#define INFLL (~(1ll<<63))#define pb push_back#define mp make_pair#define abs(a) ((a)>0?(a):-(a))#define lalal puts("*******");#define s1(x) scanf("%d",&x)#define Rep(a,b,c) for(int a=(b);a<=(c);a++)#define Per(a,b,c) for(int a=(b);a>=(c);a--)typedef long long int LL ;typedef unsigned long long int uLL ;const int N = 50000+7;const int MOD = 1e9+7;const double eps = 1e-7;const double Pi = acos(-1.0);const double E = exp(1.0);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;}void fre(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout);}template<typename T>inline T _gcd(T a,T b){return (b==0)?a:_gcd(b,a%b);}template<typename T>inline T _lcm(T a,T b){return a/_gcd(a,b)*b;}LL qmod(LL a,LL b,LL c){LL ret=1ll;while(b){if(b&1)ret=ret*a%c;b>>=1,a=a*a%c;}return ret;}/***********************************************************************/#define vi vector<int>int n;int inv(int x){ return qmod(x,n-2,n);}vi vimod(vi f,vi g){ int fz = f.size(),gz = g.size(); for(int i=0;i<fz;i++){ if(fz-i-gz < 0) break; int a=f[i]*inv(g[0])%n; for(int j=0;j<gz;j++){ int now=i+j; f[now]=((f[now]-a*g[j]%n)%n+n)%n; } } vi ans; int p=-1; for(int i=0;i<fz;i++)if(f[i]!=0){p=i;break;} if(p>=0) for(int i=p;i<fz;i++)ans.pb(f[i]); return ans;}vi gcd(vi f,vi g){ if(g.size()==0) return f; return gcd(g,vimod(f,g));}vi f,g;int main(){ int kcase = 0; while(~scanf("%d",&n)&&n){ f.clear(),g.clear(); int d,x; scanf("%d",&d); for(int i=0;i<=d;i++){ scanf("%d",&x); f.pb(x); } scanf("%d",&d); for(int i=0;i<=d;i++){ scanf("%d",&x); g.pb(x); } vi ans = gcd(f,g); int tmp = inv(ans[0]); printf("Case %d: %d",++kcase,ans.size()-1); for(int i=0;i<ans.size();i++){} printf(" %d",ans[i]*tmp%n); } puts(""); } return 0;}
- 杂(模板)
- 模板库(杂)
- C++模板(类模板、函数模板)
- 模板之类模板(数组类模板)
- Django-模板(模板语言)
- 模板(一)----->函数模板
- C++模板(二):函数模板和模板函数
- c++模板 (函数模板和类模板)
- C++中的模板(函数模板,类模板)
- Linux C/C++ 模板:类模板(主模板)
- C++模板(函数模板和类模板)
- C++模板(函数模板与模板函数)
- 类模板与模板类(C++)
- discuz 首页模板文件(门户模板)
- [模板] 求两圆相交面积(模板)
- bootstrap基础模板 (纯模板)
- freemarker模板使用(邮件模板)
- C++模板(一) ----函数模板
- swift中UIActionSheet的使用
- Unity3d 切换场景时判断场景是否加载完成
- 介绍启动管理器Grub
- 3.rabbitmq之发布订阅
- Unity3d gui自适应屏幕
- 杂(模板)
- 自定义小圆点详解
- UVA 10820 Send a Table
- 同步阻塞IO 、同步非阻塞IO 、异步阻塞IO 、异步非阻塞IO区别
- 常见浏览器兼容性问题与解决方案
- C++基础之动态分配内存
- WPF 详解模板
- Js Event Loop
- 该版本的 %1 与您运行的 Windows 版本不兼容