poj 3361 Gaussian Prime Factors 高斯素数约数

2024-05-16 16:08

本文主要是介绍poj 3361 Gaussian Prime Factors 高斯素数约数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

poj 3361 Gaussian Prime Factors

题意:

在复数 a+bj (a,b为整数)范围内,约数只有 1, -1, a+bj, -(a+bj)的称为高斯素数。求任给正整数N的所有素因子(|b|>a>0)。默认N<2e9

解法:

定理有云:
n≡3(mod 4)者,无因式分解。
n≡1(mod 4)者,可唯一分解为两个共轭高斯整数乘积。

当然做的时候并不知道!
我的思路是,既然可以分解因子,那么可以先分解成素因子,再把素因子分解出来。发现3,7等数是不能分解的,其他的素数(忽略2)都是奇数,要分解成乘积,最后不能有虚部存在,故得分解成共轭高斯整数相乘,即(a+bj)(a-bj)=n,即 a^2+b^2 = n,则a,b一奇一偶。且因为若a+bj不为素数,则可分解为 (c+dj)(e+fj),那么(a+bj)(a-bj)=(c+dj)(c-dj)(e+fj)(e-fj)=n,此时前两项与后两项都为一个实整数,与n为素数矛盾,故只要分解出来,a+bj与a-bj则一定为n的素因子。
这样就好办了,对所有的N,都先进行素因子分解,然后对每个素因子再分解其高斯素因子。我选择遍历a,b来预处理出所有素数的标准因子a+bj(另一个则为a-bj)。

自己的坑:
低估了45000内素数数量,大约为十分之一个。
使用了set,但是貌似不是这么用的。(我用来验证m-i^2是否为完全平方数,多了一个log(num_pri)的复杂度)。应该是直接检验比较快。

so,学到了STL set:

myset.count(n)  ->得到数量
myset.insert(n) ->插入
myset.find(n)   ->得到迭代器,找不到则是末尾。 .erase(.find(n))

140+行代码,500+ms过。可能是预处理和数据结构比较费时间。看别人的当场暴力分解质因数,暴力分解素数的0ms过。只能说数据太水太水啦!~

我的代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<set>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 45000;
const int maxq = 212;
struct stt{int a,b;
}q[maxn],tmpst;
vector <stt> ans;
set <int> myset;
int prim[5000];
bool isnotpri[maxn];
int prinum = 0;
int prime,sise;
int sq[maxq+1];//squarevoid ini(){memset(prim,0,sizeof prim);memset(isnotpri,false,sizeof isnotpri);memset(q,0,sizeof q);myset.clear();//memset(ans,0,sizeof ans);ans.clear();for(int i = 2; i <= maxq; i++){if(!isnotpri[i]){for(int j = i*i; j < maxn; j += i){isnotpri[j] = 1;}}}for(int i = 2; i <= maxn; i++){if(!isnotpri[i]) prim[prinum++]=i;}q[2].a=1;q[2].b=1;for(int i = 1; i <= maxq; i++){sq[i] = i*i;}int tmp;for(int i = 1; i <= maxq; i++){for(int j = i+1; j <= maxq; j += 2){tmp = sq[i]+sq[j];if(tmp >= maxn) break;if(!isnotpri[tmp]){q[tmp].a = i;q[tmp].b = j;}}}for(int i = 2; i <= maxn; i++){if(q[i].b == 0) q[i].a = i;myset.insert(i*i);}
}
void gener(int m){ans.clear();if(m == 0 || m == 1) return;for(int i = 0; i < prinum; i++){prime = prim[i];if(prime > m) break;if(m % prime == 0){ans.push_back(q[prime]);while(m % prime == 0){m /= prime;}}}if(m != 1){if(m%4==3){tmpst.a = m;tmpst.b = 0;ans.push_back(tmpst);}else{int tmp = (int)sqrt(m+0.1);int tmp2;for(int i = 1; i <= tmp; i++){if(myset.count(m-i*i)!=0){tmpst.a = i;tmpst.b = (int)sqrt(m-i*i+0.1);ans.push_back(tmpst);break;}}}}
}
bool cmp(stt i, stt j){if(i.a == j.a){return i.b < j.b;}return i.a < j.a;
}
void printout(){sise = ans.size();if(sise == 0){printf("\n");return;}sort(ans.begin(),ans.end(),cmp);int aa,bb;for(int i = 0; i < sise; i++){aa = ans[i].a, bb = ans[i].b;if(bb==0){printf(" %d",aa);}else{if(bb==1){printf(" %d+j, %d-j",aa,aa);}else{printf(" %d+%dj, %d-%dj",aa,bb,aa,bb);}}printf("%c",",\n"[i==sise-1]);}
}
int main(){freopen("in.txt","r",stdin);ini();int k = 1;int m;//return 0;while(scanf("%d",&m)!=EOF){printf("Case #%d:",k++);gener(m);printout();}return 0;
}
别人的代码:

from yjCola

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 1005
struct ele
{int a,b;bool operator < (const ele &c) const{if(a==c.a){if(abs(b)==abs(c.b))return b>c.b;elsereturn abs(b)<abs(c.b);}elsereturn a<c.a;}
}e[MAXN];
int up;
void get(int p)
{if((p-3)%4==0) e[up].a=p,e[up++].b=0;else{for(int i=1;i*i<=p;i++){int j=sqrt(1.0*(p-i*i));if(i*i+j*j==p){e[up].a=i,e[up++].b=j;e[up].a=i,e[up++].b=-j;break;}}}
}
int main()
{int cas=1,n;while(scanf("%d",&n)!=EOF){up=0;for(int i=2;i*i<=n;i++)if(n%i==0){get(i);while(n%i==0) n/=i;}if(n>1) get(n);sort(e,e+up);printf("Case #%d:",cas++);for(int i=0;i<up;i++){printf(" %d",e[i].a);if(e[i].b<0){if(e[i].b==-1) printf("-j");else printf("%dj",e[i].b);}else if(e[i].b>0){if(e[i].b==1) printf("+j");else printf("+%dj",e[i].b);}if(i<up-1) printf(",");}printf("\n");}return 0;
}
疑问:

看到有个人说 1 = j·(-j),为何1不是素因子,想想如果酱紫的话,j = 1·j, 所有的单位元都可以认为是素因子了。思考了下,可能是因为,由于a+bj和 j*(a+bj)是等价的因子,所以1 = j·(-j)又可以认为是1=1·(-1),1与本身重合,所以 1 仍是作为单元,而非素因子。

这篇关于poj 3361 Gaussian Prime Factors 高斯素数约数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/995370

相关文章

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

poj 1511 Invitation Cards(spfa最短路)

题意是给你点与点之间的距离,求来回到点1的最短路中的边权和。 因为边很大,不能用原来的dijkstra什么的,所以用spfa来做。并且注意要用long long int 来存储。 稍微改了一下学长的模板。 stack stl 实现代码: #include<stdio.h>#include<stack>using namespace std;const int M

poj 3259 uva 558 Wormholes(bellman最短路负权回路判断)

poj 3259: 题意:John的农场里n块地,m条路连接两块地,w个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts。 任务是求你会不会在从某块地出发后又回来,看到了离开之前的自己。 判断树中是否存在负权回路就ok了。 bellman代码: #include<stdio.h>const int MaxN = 501;//农场数const int

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

poj 1502 MPI Maelstrom(单源最短路dijkstra)

题目真是长得头疼,好多生词,给跪。 没啥好说的,英语大水逼。 借助字典尝试翻译了一下,水逼直译求不喷 Description: BIT他们的超级计算机最近交货了。(定语秀了一堆词汇那就省略吧再见) Valentine McKee的研究顾问Jack Swigert,要她来测试一下这个系统。 Valentine告诉Swigert:“因为阿波罗是一个分布式共享内存的机器,所以它的内存访问

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss