高精度模板(算法必备)
c语言高精度运算模板

c语言高精度运算模板
好的,下面为你提供一个C语言高精度运算模板,包括高精度加法、减法和乘法:
高精度加法:直接对位相加,当某位超过10直接取模运算,然后下一位直接对加相应多出的数即可。
高精度减法:当输入的$ss1$小于$ss2$时,需要交换两者的顺序,并率先输出一个负号。
然后执行循环,在循环中如果$a(i)<b(i)$,则直接向下一位借位,然后本位加10,$a(i)$加10。
高精度乘法:使用双重循环,$c$下标对应关系为$i+j-1$($i=j=1$开始)。
在循环中,将$a(i)$和$b(j)$相乘后的结果累加到$c(i+j-1)$中。
你可以根据实际需求对模板进行修改和调整,以满足不同的计算需求。
如果你还有其他问题,请随时向我提问。
高精度算法大全

高精度算法大全在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字.一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开放等运算.譬如一个很大的数字N >= 10^ 100, 很显然这样的数字无法在计算机中正常存储.于是, 我们想到了办法,将这个数字拆开,拆成一位一位的或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字.这样这个数字就被称谓是高精度数.对于高精度数,也要像平常数一样做加减乘除以及乘方的运算,于是就有了高精度算法:由于计算机输入计算结果的精度通常受到计算机的限制,如:在双精度方式下,计算机最多只能输出16位有效数字,如果超过16位,则只能按浮点形式输出,另外,一般计算机实数表示的范围为1038,如果超过这个范围,计算机就无法表示了。
但是我们可以通过一些简单的办法来解决这个问题。
这就是我们要说的高精度计算机。
一、基本方法:在计算机上进行高精度计算,首先要处理好以下几个基本问题:1、数据的接收与存储;2、计算结果位数的确定;3、进位处理和借位处理;4、商和余数的求法;下面我们逐一介绍一下这几个问题的解决方法。
1、数据的接收与存储:要在计算机上进行高精度计算,首先就应该有精确的输入,即计算机要精确地接收和存储数据。
通常:①、当输入的数值在计算机允许的范围内时,可以用数值型变量来接收数据。
②、当输入的数据超过计算机允许显示的精度范围时,采用字符来接收数据。
③、分离各位数字。
接收数据子模块(字符型变量接收数据):prucedure readdata(var in:array[1..100] of integer);var ch:char;i,k:integer;beginread(ch);k:=0;while ch in['0'..'9'] do begininc(k);int[k]:=ord(ch)-48;read(ch);end;end;2、计算结果位数的确定①、两数之和的位数最大为较大的数的位数加1。
高精度模板【重载运算符+压位】

⾼精度模板【重载运算符+压位】昨天做⼀道DP的题(矩阵取数游戏),本来是很简单的,但是要⽤⾼精度,⼜不想⽤__int128⽔过去(谁让NOIP不让),于是⾃⼰打了⼀个⼩时,最后成功挂了。
于是本蒟蒻痛定思痛,感觉⾼精度还是重载运算符好⽤啊,就花了⼏个⼩时打了⼀个⾃以为⽐较好记好⽤⾼精度模板:注意暂不⽀持负数,如果发现有bug欢迎指出。
/*采⽤重载运算符,压B位⽀持⾼精数赋值与输出、⾼精加(减)⾼精、⾼精乘低(⾼)精、⾼精除(模)低精、⾼精的⽐较注意:暂不⽀持负数*/#include<cstdio>#include<cstring>#include<stack>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;const int N=128,B=4;const LL base=1e4;//压B位,base为1eBstruct HP{private:int len;LL a[N];inline void clear(){while(!a[len]&&len>1) --len;}//清除前导0public:HP(){ //结构体初始化memset(a,0ll,sizeof a);len=0;}//注意因为是压B位的,所以输出要特殊处理void print(){//输出⾼精度数printf("%lld",a[len]);for(int i=len-1;i>0;--i)for(int j=base/10;j>0;j/=10) printf("%lld",a[i]/j%10);puts("");}/*以下是重载运算符*/HP& operator =(LL x){//⽤LL初始化⾼精度数 HP后加了&才可以实现像a=b=c这样连续赋值stack<char> st;string s;if(!x) return *this="0";while(x){st.push(x%10+'0');x/=10;}while(!st.empty()) s+=st.top(),st.pop();//其实就是把int转换为string再调⽤init_s()return *this=s;}HP& operator =(const string &s){//⽤string初始化⾼精度数memset(a,0ll,sizeof a);len=0;//这⾥赋值为0才可以保证重复赋值时不会出锅。
C++高精度除法及模板

C++⾼精度除法及模板本⽂介绍的是⼀个超过long long 范围的数除⼀个较⼩的数,⽤vector 模拟计算过程,同时输出商和余数Code:#include <iostream>#include <algorithm>#include <vector>using namespace std;vector<int > A;int b, r;vector<int > div(vector<int > &a, int b, int &r){vector<int > res;int t = 0;for (int i = a.size() - 1; i >= 0; i --){t = t* 10 + a[i];res.push_back(t / b);t %= b;r = t;}reverse(res.begin(), res.end());while (!res.back() && res.size() > 1) res.pop_back();return res;}int main(){string a;cin >> a >> b;for (int i = a.size() - 1; i >=0 ; i --) A.push_back(a[i] ^ 48);auto c = div(A, b, r);for (int i = c.size() - 1; i >= 0; i --) cout << c[i];cout << endl;cout << r << endl;return 0;}字符串输⼊,由低到⾼位存⼊vector ,在从vector ⾼位开始算,这样算的结果是有前导0的,所以要reverse ⼀下,前导零就变成了后缀0,去掉后返回,再逆序输出即可。
高精度WENO有限体积格式

插值多项式的构造
上的ENO插值多项式 p2 (x, y),需要六个三角 为了构造 ∆0 上的 插值多项式 形网格, 形网格,不妨设阴影部分 为选定的三角形网格模板, 为选定的三角形网格模板,记为
S = {∆0 , ∆i , ∆ j , ∆k , ∆ia , ∆ jb}
有限体积法选用的一般三角形计算网格
Jiang对WENO格式进行了改进和提高, Jiang对WENO格式进行了改进和提高,提出了 格式进行了改进和提高 一种新的光滑措施, 一种新的光滑措施,能使这种格式在光滑的
阶精度, ENO格式达到 区域达到 (2r −1) 阶精度,在ENO格式达到 r 阶精度的 情况下) 在间断解区域权设置系数近似于零, 情况下),在间断解区域权设置系数近似于零,可达到 基本无震荡的效果。 基本无震荡的效果。 上述进行的研究,大多局限于结构网格上。近年来, 上述进行的研究,大多局限于结构网格上。近年来, 在非结构网格上开展这方面的工作也有了一些进展, 在非结构网格上开展这方面的工作也有了一些进展,如 Abgrall,Harten对ENO格式进行了研究,Hu等人对 格式进行了研究,Hu等人对WENO Abgrall,Harten对ENO格式进行了研究,Hu等人对WENO 格式进行了研究。 格式进行了研究。但总起来说开展这方面的研究工作不 还不很成熟,没有形成全面系统的理论体系。 多,还不很成熟,没有形成全面系统的理论体系。 近年来又出现了用点云离散计算区域的无网格算法, 近年来又出现了用点云离散计算区域的无网格算法, 适合处理复杂的气动外形。 适合处理复杂的气动外形。
选取十个三角形网格作为基构造weno二次插值多项式选取的典型的网格模板如下图特殊情况的网格模板i特殊情况的网格模板ii为了构造上的eno插值多项式需要六个三角形网格插值多项式需要六个三角形网格02yxp不妨设阴影部分00iikjjkaibkkbjaiajbiajbibkakbja插值多项式的构造为选定的三角形网格模板记为jbiakjis0上述网格三角形可以重合有限体积法选用的一般三角形计算网格
高精度乘法模板

高精度乘法模板一、引言在数学运算中,乘法是一种基本的运算方式。
在现实生活中,我们经常需要进行大数相乘的运算,比如计算金融数据、密码学中的加密算法等。
然而,由于计算机的内存限制和运算速度的限制,直接进行大数相乘是一件非常困难的事情。
因此,我们需要一种高精度乘法模板来解决这个问题。
二、高精度乘法模板的实现思路高精度乘法模板的实现思路可以分为以下几个步骤:1. 将两个大数转化为字符串由于计算机内存的限制,我们无法直接使用整型或浮点型变量来存储大数。
因此,我们可以将大数转化为字符串来进行处理。
在C++中,可以使用string类来方便地处理字符串。
2. 将字符串表示的大数转化为数组为了方便计算,我们可以将字符串表示的大数转化为数组。
数组的每个元素表示大数的一位数字。
在C++中,可以使用vector容器来存储数组。
3. 实现乘法运算乘法运算的实现可以采用竖式乘法的方式。
具体步骤如下:•遍历第一个大数的每一位数字,与第二个大数的每一位数字相乘,并将结果保存在一个新的数组中。
•对新数组进行进位处理,确保每一位数字都在0-9的范围内。
•将新数组转化为字符串表示的大数。
4. 处理特殊情况在实际应用中,还需要考虑一些特殊情况的处理,比如大数为0的情况、大数为负数的情况等。
三、高精度乘法模板的代码实现下面是一个简单的C++代码实现示例:#include <iostream>#include <vector>#include <string>using namespace std;string multiply(string num1, string num2) {int m = num1.size();int n = num2.size();vector<int> res(m + n, 0);for (int i = m - 1; i >= 0; i--) {for (int j = n - 1; j >= 0; j--) {int mul = (num1[i] - '0') * (num2[j] - '0');int p1 = i + j, p2 = i + j + 1;int sum = mul + res[p2];res[p1] += sum / 10;res[p2] = sum % 10;}}string result = "";for (int i = 0; i < res.size(); i++) {if (!(result.empty() && res[i] == 0)) {result.push_back(res[i] + '0');}}return result.empty() ? "0" : result;}int main() {string num1 = "123";string num2 = "456";string result = multiply(num1, num2);cout << result << endl;return 0;}四、高精度乘法模板的应用举例高精度乘法模板可以应用于很多实际问题中。
第1章--高精度计算(C++版)PPT课件

2021/6/4
856 × 25 4280 1712 21400
图3
A3A2A1 × B2B1 C’4C’3 C’2 C’1 C”5C”4C”3C”2 C6C 5C4C 3C2C1 图4
11
高精度乘法的参考程序: #include<iostream> #include<cstring> #include<cstdio> using namespace std; int main() {
示例:123456789 ÷45 = 1’ 2345’ 6789 ÷ 45 = 274’ 3484
∵ 1 / 45 = 0 , 1%45=1 ∴ 取12345 / 45 = 274 ∵ 12345 % 45 = 15 ∴ 取156789/45 = 3484 ∴ 答案为2743484, 余数为156789%45 = 9
//按位相除 //删除前导0
2021/6/4
16
实质上,在做两个高精度数运算时候,存储高精度数的 数组元素可以不仅仅只保留一个数字,而采取保留多位数 (例如一个整型或长整型数据等),这样,在做运算(特别 是乘法运算)时,可以减少很多操作次数。例如图5就是采用 4位保存的除法运算,其他运算也类似。具体程序可以修改上 述例题予以解决,程序请读者完成。
图5
2021/6/4
【算法分析】 做除法时,每一次上商的值都在0~9,每次求得的余
数连接以后的若干位得到新的被除数,继续做除法。因此, 在做高精度除法时,要涉及到乘法运算和减法运算,还有移 位处理。当然,为了程序简洁,可以避免高精度除法,用0~ 9次循环减法取代得到商的值。这里,我们讨论一下高精度数 除以单精度数的结果,采取的方法是按位相除法。
ACM常用算法模板

专用模板目录:一、图论1.最大团2.拓扑排序3.最短路和次短路4.SAP模板5.已知各点度,问能否组成一个简单图6.KRUSKAL7. Prim算法求最小生成树8. Dijkstra9 . Bellman-ford10. SPFA11. Kosaraju 模板12. tarjan 模板二、数学1. 剩余定理2. N!中质因子P的个数3.拓展欧几里得4.三角形的各中心到顶点的距离和5.三角形外接圆半径周长6.归并排序求逆序数7. 求N!的位数8.欧拉函数9. Miller-Rabin,大整数分解,求欧拉函数10. 第一类斯特林数11.计算表达式12.约瑟夫问题13.高斯消元法14. Baby-step,giant-step n是素数.n任意15. a^b%c=a ^(b%eular(c)+eular(c)) % c16.判断第二类斯特林数的奇偶性17.求组合数C(n,r)18.进制转换19.Ronberg算法计算积分20.行列式计算21. 返回x 的二进制表示中从低到高的第i位22.高精度运算 +-*/23.超级素数筛选三、数据结构1.树状数组2.线段树求区间的最大、小值3.线段树求区间和4.单调队列5.KMP模板6. 划分树,求区间第k小数7.最大堆,最小堆模板8. RMQ模板求区间最大、最小值9.快速排序,归并排序求逆序数.10.拓展KMP四、计算几何1.凸包面积2.Pick公式求三角形内部有多少点3.多边形边上内部各多少点以及面积pick4.平面最远点对5.判断矩形是否在矩形内6.判断点是否在多边形内7.判断4个点(三维)是否共面8.凸包周长9.等周定理变形一直两端点和周长求最大面积10.平面最近点对11.单位圆最多覆盖多少点(包括边上)12.多边形费马点求点到多边形各个点的最短距离13.矩形并周长14.zoj 2500 求两球体积并一、图论1.最大团#include<iostream>#include<algorithm>using namespace std;int n,m;int cn;//当前顶点数int best;//当前最大顶点数int vis[50];//当前解int bestn[50];//最优解int map[50][50];//临界表void dfs(int i){if(i>n){for(int j=1;j<=n;j++) bestn[j]=vis[j];best=cn;return ;}int ok=1;for(int j=1;j<i;j++){if(vis[j]==1&&map[i][j]==0){ok=0;break;}}if(ok){//进入左子树vis[i]=1;cn++;dfs(i+1);cn--;}if(cn+n-i>best){//进入右子树vis[i]=0;dfs(i+1);}}int main(){while(scanf("%d%d",&n,&m)==2){memset(vis,0,sizeof(vis));memset(map,0,sizeof(map));while(m--){int p,q;scanf("%d%d",&p,&q);map[p][q]=map[q][p]=1;//无向图}cn=0;best=0;dfs(1);printf("%d\n",best);}return 0;}2.拓扑排序#include<iostream>#include<cstring>using namespace std;int map[105][105],in[105],vis[105],ans[105],n;int flag;void dfs(int step){if(flag) return ;if(step==n+1) {flag=1; printf("%d",ans[1]);for(int i=2;i<=n;i++) printf(" %d",ans[i]);printf("\n");return ;}for(int i=1;i<=n;i++){if(vis[i]==0&&in[i]==0){vis[i]=1;for(int j=1;j<=n;j++){if(map[i][j]>0){map[i][j]=-map[i][j];in[j]--;}}ans[step]=i;dfs(step+1);vis[i]=0;for(int j=1;j<=n;j++){if(map[i][j]<0){map[i][j]=-map[i][j];in[j]++;}}}}}int main(){while(scanf("%d",&n)==1){flag=0;memset(map,0,sizeof(map));memset(vis,0,sizeof(vis));memset(in,0,sizeof(in));for(int i=1;i<=n;i++){int t;while(scanf("%d",&t),t){map[i][t]=1;in[t]++;}}dfs(1);}return 0;}3.最短路和次短路#include<iostream>#include<cstdio>#include<vector>#include<cstring>using namespace std;class Node{public:int e,w;//表示终点和边权};const int inf=(1<<25);int main(){int ci;cin>>ci;while(ci--){vector<Node> G[1005];//用邻接表存边int n,m;cin>>n>>m;for(int i=1;i<=m;i++){Node q;int u;cin>>u>>q.e>>q.w;G[u].push_back(q);}int s,f;//起点和终点cin>>s>>f;//dijkstra 求最短路和次短路int flag[1005][2];int dis[1005][2],cnt[1005][2];//0表示最短路,1表示次短路memset(flag,0,sizeof(flag));for(int i=1;i<=n;i++) dis[i][0]=dis[i][1]=inf;dis[s][0]=0;cnt[s][0]=1;//初始化for(int c=0;c<2*n;c++) //找最短路和次短路,故要进行2*n次循环也可以改成while(1){int temp=inf,u=-1,k;//找s-S'集合中的最短路径,u记录点的序号,k记录是最短路或者是次短路for(int j=1;j<=n;j++){if(flag[j][0]==0&&temp>dis[j][0]) temp=dis[j][0],u=j,k=0;else if(flag[j][1]==0&&temp>dis[j][1]) temp=dis[j][1],u=j,k=1;}if(temp==inf) break;//S'集合为空或者不联通,算法结束//更新路径flag[u][k]=1;for(int l=0;l<G[u].size();l++){int d=dis[u][k]+G[u][l].w,j=G[u][l].e;//important//4种情况if(d<dis[j][0]){dis[j][1]=dis[j][0];cnt[j][1]=cnt[j][0];dis[j][0]=d;cnt[j][0]=cnt[u][k];}else if(d==dis[j][0]){cnt[j][0]+=cnt[u][k];}else if(d<dis[j][1]){dis[j][1]=d;cnt[j][1]=cnt[u][k];}else if(d==dis[j][1]){cnt[j][1]+=cnt[u][k];}}}int num=cnt[f][0];//最短路int cc=cnt[f][1];//次短路}return 0;}4.SAP模板#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int inf=(1<<31)-1;const int point_num=300;int cap[point_num][point_num],dist[point_num],gap[point_num];//初始化见main里面int s0,t0,n;//源,汇和点数int find_path(int p,int limit=0x3f3f3f3f){if(p==t0) return limit;for(int i=0;i<n;i++)if(dist[p]==dist[i]+1 && cap[p][i]>0){int t=find_path(i,min(cap[p][i],limit));if(t<0) return t;if(t>0){cap[p][i]-=t;cap[i][p]+=t;return t;}}int label=n;for(int i=0;i<n;i++) if(cap[p][i]>0) label=min(label,dist[i]+1);if(--gap[dist[p]]==0 || dist[s0]>=n ) return -1;++gap[dist[p]=label];return 0;}int sap(){//初始化s,ts0=0,t0=n-1;int t=0,maxflow=0;gap[0]=n;while((t=find_path(s0))>=0) maxflow+=t;return maxflow;}int main(){int ci;while(cin>>ci>>n){//初始化memset(cap,0,sizeof(cap));memset(dist,0,sizeof(dist));memset(gap,0,sizeof(gap));//初始化capwhile(ci--){int x,y,c;cin>>x>>y>>c;x--;y--;cap[x][y]+=c;//因题而异}int ans=sap();cout<<ans<<endl;}return 0;}5.已知各点度,问能否组成一个简单图#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int inf=(1<<30);int d[1100];bool cmp(int x,int y){return x>y;}int main(){int ci;scanf("%d",&ci);while(ci--){int n,flag=1,cnt=0;scanf("%d",&n); for(int i=0;i<n;i++){scanf("%d",&d[i]);if(d[i]>n-1||d[i]<=0) flag=0; cnt+=d[i];}if(flag==0||cnt%2){printf("no\n");continue;}sort(d,d+n,cmp);for(int l=n;l>0;l--){for(int i=1;i<l&&d[0];i++){d[0]--,d[i]--;if(d[i]<0){flag=0;break;}}if(d[0]) flag=0;if(flag==0) break;d[0]=-inf;sort(d,d+l,cmp);}if(flag) printf("yes\n");else printf("no\n");}return 0;}6.KRUSKAL#include<iostream>#include<algorithm>using namespace std;int u[15005],v[15005],w[15005],fath[15005],r[15005];int ans1[15005],ans2[15005];bool cmp(int i,int j){return w[i]<w[j];}int find(int x){return fath[x]==x?x:fath[x]=find(fath[x]);}int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++) fath[i]=i;for(int i=1;i<=m;i++) r[i]=i;for(int i=1;i<=m;i++){cin>>u[i]>>v[i]>>w[i];}sort(r+1,r+m+1,cmp);int maxn=0,ans=0,k=0;for(int i=1;i<=m;i++){int e=r[i];int x=find(u[e]),y=find(v[e]);if(x!=y){ans+=w[e];fath[x]=y;if(w[e]>maxn) maxn=w[e];ans1[k]=u[e];ans2[k++]=v[e];}}return 0;}7.prime求最小生成树语法:prim(Graph G,int vcount,int father[]);参数:G:图,用邻接矩阵表示vcount:表示图的顶点个数father[]:用来记录每个节点的父节点返回值:null注意:常数max_vertexes 为图最大节点数常数infinity为无穷大源程序:#define infinity 1000000#define max_vertexes 5typedef int Graph[max_vertexes][max_vertexes];void prim(Graph G,int vcount,int father[]){int i,j,k;intlowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes]; for (i=0;i<vcount;i++){lowcost[i]=G[0][i];closeset[i]=0;used[i]=0;father[i]=-1;}used[0]=1;for (i=1;i<vcount;i++){j=0;while (used[j]) j++;for (k=0;k<vcount;k++)if ((!used[k])&&(lowcost[k]<lowcost[j])) j=k;father[j]=closeset[j];used[j]=1;for (k=0;k<vcount;k++)if (!used[k]&&(G[j][k]<lowcost[k])){ lowcost[k]=G[j][k];closeset[k]=j; }}}8.Dijkstra语法:result=Dijkstra(Graph G,int n,int s,int t, int path[]); 参数:G:图,用邻接矩阵表示n:图的顶点个数s:开始节点t:目标节点path[]:用于返回由开始节点到目标节点的路径返回值:最短路径长度注意:输入的图的权必须非负顶点标号从0 开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Dijkstra(Graph G,int n,int s,int t, int path[]){int i,j,w,minc,d[max_vertexes],mark[max_vertexes];for (i=0;i<n;i++) mark[i]=0;for (i=0;i<n;i++){ d[i]=G[s][i];path[i]=s; }mark[s]=1;path[s]=0;d[s]=0;for (i=1;i<n;i++){minc=infinity;w=0;for (j=0;j<n;j++)if ((mark[j]==0)&&(minc>=d[j])) {minc=d[j];w=j;}mark[w]=1;for (j=0;j<n;j++)if((mark[j]==0)&&(G[w][j]!=infinity)&&(d[j]>d[w]+G[w][j])){ d[j]=d[w]+G[w][j];path[j]=w; }}return d[t];}9.Bellman-ford语法:result=Bellman_ford(Graph G,int n,int s,int t,int path[],int success);参数:G:图,用邻接矩阵表示n:图的顶点个数s:开始节点t:目标节点path[]:用于返回由开始节点到目标节点的路径success:函数是否执行成功返回值:最短路径长度注意:输入的图的权可以为负,如果存在一个从源点可达的权为负的回路则success=0顶点标号从0 开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Bellman_ford(Graph G,int n,int s,int t,int path[],int success){int i,j,k,d[max_vertexes];for (i=0;i<n;i++) {d[i]=infinity;path[i]=0;}d[s]=0;for (k=1;k<n;k++)for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]){d[j]=d[i]+G[i][j];path[j]=i;}success=0;for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]) return 0;success=1;return d[t];}10. SPFA#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;const __int64 maxn=1001000;const __int64 inf=1000100000;struct edge//邻接表{__int64 t,w;//s->t=w;__int64 next;//数组模拟指针};__int64 p[maxn],pf[maxn];//邻接表头节点edge G[maxn],Gf[maxn];//邻接表__int64 V,E;//点数[1-n] 边数__int64 dis[maxn];__int64 que[maxn],fro,rear;//模拟队列__int64 vis[maxn];__int64 inque[maxn];//入队次数bool spfa(__int64 s0){fro=rear=0;for(__int64 i=1;i<=V;i++) dis[i]=inf;dis[s0]=0;memset(vis,0,sizeof(vis));memset(inque,0,sizeof(inque));que[rear++]=s0;vis[s0]=1;inque[s0]++;while(fro!=rear){__int64 u=que[fro];fro++;if(fro==maxn) fro=0;vis[u]=0;for(__int64 i=p[u];i!=-1;i=G[i].next){__int64 s=u,t=G[i].t,w=G[i].w;if(dis[t]>dis[s]+w){dis[t]=dis[s]+w;if(vis[t]==0){que[rear++]=t,vis[t]=1;inque[t]++;if(inque[t]>V) return false;if(rear==maxn) rear=0;}}}}return true;}int main(){__int64 ci;scanf("%I64d",&ci);while(ci--){scanf("%I64d%I64d",&V,&E);memset(p,-1,sizeof(p));memset(pf,-1,sizeof(pf)); for(__int64 i=0;i<E;i++){__int64 u,v,w;scanf("%I64d%I64d%I64d",&u,&v,&w);G[i].t=v;G[i].w=w;G[i].next=p[u];p[u]=i;Gf[i].t=u;Gf[i].w=w;Gf[i].next=pf[v];pf[v]=i;}__int64 ans=0;spfa(1);//求第一个点到其他点的最短距离和for(__int64 i=1;i<=V;i++) ans+=dis[i];//反方向再来一次spfa 求其他点到第一个点的最短距离和 for(__int64 i=1;i<=V;i++) p[i]=pf[i];for(__int64 i=0;i<E;i++) G[i]=Gf[i];spfa(1);for(__int64 i=1;i<=V;i++) ans+=dis[i];printf("%I64d\n",ans);}return 0;}11.Kosaraju模板#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;struct edge{int t,w;//u->t=w;int next;};int V,E;//点数(从1开始),边数int p[maxn],pf[maxn];//邻接表原图,逆图edge G[maxn],Gf[maxn];//邻接表原图,逆图int l,lf;void init(){memset(p,-1,sizeof(p));memset(pf,-1,sizeof(pf));l=lf=0;}void addedge(int u,int t,int w,int l){G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}void addedgef(int u,int t,int w,int lf){Gf[l].w=w;Gf[l].t=t;Gf[l].next=pf[u];pf[u]=l;}///Kosaraju算法,返回为强连通分量个数bool flag[maxn]; //访问标志数组int belg[maxn]; //存储强连通分量,其中belg[i]表示顶点i属于第belg[i]个强连通分量int numb[maxn]; //结束时间(出栈顺序)标记,其中numb[i]表示离开时间为i的顶点//用于第一次深搜,求得numb[1..n]的值void VisitOne(int cur, int &sig){flag[cur] = true;for (int i=p[cur];i!=-1;i=G[i].next){if (!flag[G[i].t]){VisitOne(G[i].t,sig);}}numb[++sig] = cur;}//用于第二次深搜,求得belg[1..n]的值void VisitTwo(int cur, int sig){flag[cur] = true;belg[cur] = sig;for (int i=pf[cur];i!=-1;i=Gf[i].next){if (!flag[Gf[i].t]){VisitTwo(Gf[i].t,sig);}}//Kosaraju算法,返回为强连通分量个数int Kosaraju_StronglyConnectedComponent(){int i, sig;//第一次深搜memset(flag,0,sizeof(flag));for ( sig=0,i=1; i<=V; ++i ){if ( false==flag[i] ){VisitOne(i,sig);}}//第二次深搜memset(flag,0,sizeof(flag));for ( sig=0,i=V; i>0; --i ){if ( false==flag[numb[i]] ){VisitTwo(numb[i],++sig);}}return sig;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int u=i,t,w=1;while(scanf("%d",&t)==1&&t){E++;addedge(u,t,w,l++);addedgef(t,u,w,lf++);}}int ans=Kosaraju_StronglyConnectedComponent(); printf("%d\n",ans);}return 0;12.tarjan模板//自己模板#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;int V,E;//点数(1) 边数struct edge//邻接表{int t,w;//u->t=w;int next;};int p[maxn];//表头节点edge G[maxn];int l;void init(){memset(p,-1,sizeof(p));l=0;}//添加边void addedge(int u,int t,int w,int l)//u->t=w;{G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}//tarjan算法求有向图强联通分量int dfn[maxn],lowc[maxn];//dfn[u]节点u搜索的次序编号,lowc[u]u或者u的子树能够追溯到的栈中的最早的节点int belg[maxn];//第i个节点属于belg[i]个强连通分量int stck[maxn],stop;//stck栈int instck[maxn];//第i个节点是否在栈中int scnt;//强联通分量int index;void dfs(int i){dfn[i]=lowc[i]=++index;instck[i]=1;//节点i入栈stck[++stop]=i;for(int j=p[i];j!=-1;j=G[j].next){int t=G[j].t;//更新lowc数组if(!dfn[t])//t没有遍历过{dfs(t);if(lowc[i]>lowc[t]) lowc[i]=lowc[t];}//t是i的祖先节点else if(instck[t]&&lowc[i]>dfn[t]) lowc[i]=dfn[t];}//是强连通分量的根节点if(dfn[i]==lowc[i]){scnt++;int t;do{t=stck[stop--];instck[t]=0;belg[t]=scnt;}while(t!=i);}}int tarjan(){stop=scnt=index=0;memset(dfn,0,sizeof(dfn));memset(instck,0,sizeof(instck));for(int i=1;i<=V;i++){if(!dfn[i]) dfs(i);}return scnt;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int x;while(scanf("%d",&x)==1&&x){E++;addedge(i,x,1,l++);}}int ans=tarjan();printf("%d\n",ans);}return 0;}//吉大模板邻接表版#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;int V,E;//点数(1) 边数struct edge//邻接表{int t,w;//u->t=w;int next;};int p[maxn];//表头节点edge G[maxn];int l;void init(){memset(p,-1,sizeof(p));l=0;}//添加边void addedge(int u,int t,int w,int l)//u->t=w;{G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}//tarjan算法求有向图强联通分量int dfn[maxn],lowc[maxn];//dfn[u]节点u搜索的次序编号,lowc[u]u或者u的子树能够追溯到的栈中的最早的节点int stck[maxn],stop;//stck栈int pre[maxn];//int scnt;//强联通分量int cnt;//void dfs(int v)//1-V{int t,minc=lowc[v]=pre[v]=cnt++;stck[stop++]=v;for(int i=p[v];i!=-1;i=G[i].next){int pv=G[i].t;if(pre[pv]==-1) dfs(pv);if(lowc[pv]<minc) minc=lowc[pv]; }if(minc<lowc[v]){lowc[v]=minc;return ;}do{dfn[t=stck[--stop]]=scnt;lowc[t]=V;}while(t!=v);++scnt;}int tarjan(){stop=cnt=scnt=0;memset(pre,-1,sizeof(pre));for(int i=1;i<=V;i++){if(pre[i]==-1) dfs(i);}return scnt;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int x;while(scanf("%d",&x)==1&&x){E++;addedge(i,x,1,l++);}}int ans=tarjan();printf("%d\n",ans);}return 0;}二、数学1.剩余定理int mod(int c[],int b[],int n){int all_multy=1,sum=0;int i,j,x[5];for(i=0;i<n;i++)all_multy*=c[i];for(i=0;i<n;i++)x[i]=all_multy/c[i];for(i=0;i<n;i++){j=1;while((x[i]*j)%c[i]!=1)j++;x[i]*=j;}for(i=0;i<n;i++)sum+=(b[i]*x[i]);return sum%all_multy;}2.N!中质因子P的个数//对于任意质数p,n!中有(n/p+n/p^2+n/p^3+...)个质因子p。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
高精度计算模板注意:减法、除法要用到compare函数乘法需要加法的部分,加法需要减法部分#include <iostream>#include <string>using namespace std;int compare(string str1, string str2){if(str1.size() > str2.size())return 1;else if(str1.size() < str2.size())return -1;elsereturn pare(str2);}int main(){char ch;string s1, s2, res;while(cin >> ch) {cin >> s1>> s2;switch(ch) {case '+': res = ADD_INT(s1, s2); break; //高精度加法case '-': res = MINUS_INT(s1, s2); break; //高精度减法case '*': res = MULTIPLY_INT(s1, s2); break; //高精度乘法case '/': res = DIV_INT(s1, s2); break; //高精度除法,返回商case 'm': res = MOD_INT(s1, s2); break; //高精度除法,返回余数 default : break;}cout << res<< endl;}return(0);}string ADD_INT(string str1, string str2){string MINUS_INT(string str1, string str2);int sign = 1;string str;if(str1[0] == '-') {if(str2[0] == '-') {sign = -1;str = ADD_INT(str1.erase(0, 1), str2.erase(0, 1));}else {str = MINUS_INT(str2, str1.erase(0, 1));}}else {if(str2[0] == '-')str = MINUS_INT(str1, str2.erase(0, 1));else {string::size_type l1, l2;int i;l1 = str1.size(); l2 = str2.size();if(l1 < l2) {for(i = 1; i <= (int)(l2 - l1); i++)str1 = "0" + str1;}else {for(i = 1; i <= (int)(l1 - l2); i++)str2 = "0" + str2;}int int1 = 0, int2 = 0;for(i = str1.size() - 1; i >= 0; i--) {int1 = (int(str1[i]) - 48 + int(str2[i]) - 48 + int2) %10; int2 = (int(str1[i]) - 48 + int(str2[i]) - 48 +int2) / 10; str = char(int1 + 48) + str;}if(int2 != 0) str = char(int2 + 48) + str;}}//运算后处理符号位if((sign == -1) && (str[0] !='0'))str = "-" + str;return str;}string MINUS_INT(string str1, string str2){string MULTIPLY_INT(string str1, string str2);int i,sign = 1;string str;if(str2[0] == '-')str = ADD_INT(str1, str2.erase(0, 1));else {int res = compare(str1, str2);if(res == 0) return "0";if(res < 0) {sign = -1;string temp = str1;str1 = str2;str2 = temp;}string::size_type tempint;tempint = str1.size() - str2.size();for(int i = str2.size() - 1; i >= 0; i--) {if(str1[i + tempint] < str2[i]) {str1[i + tempint - 1] = char(int(str1[i + tempint - 1]) - 1); str = char(str1[i + tempint] - str2[i] + 58) + str;}elsestr = char(str1[i + tempint] - str2[i] + 48) + str;}for(i = tempint - 1; i >= 0; i--)str = str1[i] + str;}//去除结果中多余的前导0str.erase(0, str.find_first_not_of('0'));if(str.empty()) str = "0";if((sign == -1) && (str[0] !='0'))str = "-" + str;return str;}string MULTIPLY_INT(string str1, string str2){int sign = 1;string str;if(str1[0] == '-') {sign *= -1;str1 = str1.erase(0, 1);}if(str2[0] == '-') {sign *= -1;str2 = str2.erase(0, 1);}int i, j;string::size_type l1, l2;l1 = str1.size(); l2 = str2.size();for(i = l2 - 1; i >= 0; i --) {//实现手工乘法string tempstr;int int1 = 0, int2 = 0, int3 = int(str2[i]) - 48;if(int3 != 0) {for(j = 1; j <= (int)(l2 - 1 - i); j++)tempstr = "0" + tempstr;for(j = l1 - 1; j >= 0; j--) {int1 = (int3 * (int(str1[j]) - 48) + int2) % 10; int2 = (int3 * (int(str1[j]) - 48) + int2) / 10;tempstr = char(int1 + 48) + tempstr;}if(int2 != 0) tempstr = char(int2 + 48) + tempstr;}str = ADD_INT(str, tempstr);}//去除结果中的前导0str.erase(0, str.find_first_not_of('0'));if(str.empty()) str = "0";if((sign == -1) && (str[0] !='0'))str = "-" + str;return str;}string DIVIDE_INT(string str1, string str2, int flag){//flag = 1时,返回商; flag = 0时,返回余数string quotient, residue;int sign1 = 1, sign2 = 1, i;if(str2 == "0") { //判断除数是否为0quotient = "ERROR!";residue = "ERROR!";if(flag == 1) return quotient;else return residue;}if(str1 == "0") { //判断被除数是否为0quotient = "0";residue = "0";}if(str1[0] == '-') {str1 = str1.erase(0, 1);sign1 *= -1;sign2 = -1;}if(str2[0] == '-') {str2 = str2.erase(0, 1);sign1 *= -1;}int res = compare(str1, str2);if(res < 0) {quotient = "0";residue = str1;}else if(res == 0) {quotient = "1";residue = "0";}else {string::size_type l1, l2;l1 = str1.size(); l2 = str2.size();string tempstr;tempstr.append(str1, 0, l2 - 1);//模拟手工除法for(i = l2 - 1; i < l1; i++) {tempstr = tempstr + str1[i];for(char ch = '9'; ch >= '0'; ch --) {string str;str = str + ch;if(compare(MULTIPLY_INT(str2, str), tempstr) <= 0){quotient = quotient + ch;tempstr = MINUS_INT(tempstr, MULTIPLY_INT(str2, str));break;}}}residue = tempstr;}//去除结果中的前导0quotient.erase(0, quotient.find_first_not_of('0'));if(quotient.empty()) quotient = "0";if((sign1 == -1) && (quotient[0] !='0'))quotient = "-" + quotient;if((sign2 == -1) && (residue[0] !='0'))residue = "-" + residue;if(flag == 1) return quotient;else return residue;}//高精度除法,返回商string DIV_INT(string str1, string str2){return DIVIDE_INT(str1, str2, 1);}//高精度除法,返回余数string MOD_INT(string str1, string str2){return DIVIDE_INT(str1, str2, 0);}。