随笔分类 -  数论

摘要:题意:给定N个数a1,a2,a3...aN,现在要求最小的n满足 n!/(a1!*a2!*...*aN!) 是一个正整数的最小的n。分析:这题的想法很明确,就是分解a1!*a2!*...*aN!,把其分解成质因子相乘的形式,这个都很熟悉了,然后就是对每一个质因子二分搜索出一个数字下界,最后求其中最大的一个数,问题的关键就是如何分解这样一个表达式成一个质因子相乘的形式。使用一个cnt数组来表示每一个数的在乘积中出现的次数,然后从后往前假设一个数出现了k次,那么如果这个数是素数则不用更新,如果一个数是合数则将其分解成两部分,一个是该数最小的质因子,一个是除以这个质因子之后的值,接着一直做下去,就能 阅读全文
posted @ 2013-10-08 17:22 沐阳 阅读(657) 评论(0) 推荐(0) 编辑
摘要:题意:给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。分析:反素数定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0=t2>=t3>=....那题题目相当于求解小于等于N中,最大的反素数。搜索即可。这个搜索的速度是很快的。#include #include #include #include #include #include #include using namespace std;typedef long long LL;LL n;vectorvp;mapmp 阅读全文
posted @ 2013-09-05 20:04 沐阳 阅读(891) 评论(0) 推荐(1) 编辑
摘要:题意:给定一个N*N个网格(每条边上共有N+1个点),从这个网格中取出三个点构成三角形,问一共可以构成多少种三角形。解法:首先令N' = N+1,那么不考虑直线相交的情况下从N'*N'个点中选出三个点的方案数为C(3, N'*N');然后考虑到每条平行于水平和垂直线的线段上共有2*N'*C(3, N')种情况需要减去,最后还要减去斜线直线上的情况。斜线上则只考虑从左上到右下的情况,乘以2表示从右到左是对称的。对于每一种斜线的情况都可以将左上端点和右下端点固定,然后就可以看作是一个矩形对角线上除去两个端点外,中间还有多少个点的问题了,对于这 阅读全文
posted @ 2013-06-11 22:27 沐阳 阅读(305) 评论(0) 推荐(0) 编辑
摘要:题意:非常简单,就是求一个表达式的最后结果。解法:http://blog.csdn.net/magic____/article/details/9021169代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;LL a, b, n, m;struct Matrix { int r, c; int a[2][2]; 阅读全文
posted @ 2013-06-07 00:02 沐阳 阅读(769) 评论(0) 推荐(0) 编辑
摘要:http://www.cnblogs.com/skyiv/archive/2010/03/27/1698550.html关键点在于通过记录一个数被分解的方案中包不包含1来考虑。得出结论有:f[2*N+1] = f[2*N]f[2*N] = f[2*N-1] + f[N]f[2*N] = f[0]+f[1]+...+f[N]代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <iostream>#include <algorithm>using names 阅读全文
posted @ 2013-05-29 16:14 沐阳 阅读(322) 评论(0) 推荐(0) 编辑
摘要:题意:要求给出一个数N的余数系的三个排列A, B, C,其中使得对于任意的 i 满足(A[i] + B[i]) % N = C[i]。例如N=5的时候有一下排列:A: 1 4 3 2 0B: 1 0 2 4 3C: 2 4 0 1 3解法:首先排列如果存在的话,肯定是不唯一的,因为可以随意交换A,B,C的相同两列使得结果仍然满足。对于一个给定的N,我们可以列出一下一张图:横纵坐标反应了余数相加的情况:0 1 2 3 41 2 3 4 02 3 4 0 13 4 0 1 24 0 1 2 3只要取从左上到右下的对角线即可。以上只能够保证N为奇数的时候有解,不足以说明白偶数为何无解。还有一种观点现 阅读全文
posted @ 2013-05-13 16:06 沐阳 阅读(355) 评论(0) 推荐(0) 编辑
摘要:题意:给定一个数N(1<=N<=10000),求N的一个最小的倍数能够被N整除。解法:粗看起来题意简单,但是确无从下手,其实正确的解法就是通过搜索来搞定,由于N不太,因此N的余数类也不会很大,采用从小到大的枚举策略能够使得后面达到的同余类状态不及前面的优秀,这样就能够在非常短的时间内找到答案。bfs过程中对于在状态与状态之间建立前驱指针,这样就能够输出最后的结果。一个状态需要记录以下值:1.当前状态对N的余数;2.当前放置的数字;3.前驱指针。状态之间的转移:mod' = (mod*10 + digit) % N从1位开始依次枚举,然后扩大到2位,3位.....代码如下:# 阅读全文
posted @ 2013-04-25 13:33 沐阳 阅读(811) 评论(0) 推荐(0) 编辑
摘要:详见代码:#include <cstdlib>#include <cstring>#include <cstdio>#include <cmath>using namespace std;// 给定一个数N,求1-N的所有数与这个数的gcd之和// 观察gcd函数,我们可以得知那些与N互质的数的gcd一定为1,也就是欧拉函数 // 那么那些不互质的数有gcd(x, N) = d // 也就是gcd(x/d, N/d) = 1,所以我们继续求N/d的欧拉函数就可以了 int eular(int x) { // 直接对某一个数进行素因子分解求解 in 阅读全文
posted @ 2013-01-04 21:06 沐阳 阅读(295) 评论(0) 推荐(0) 编辑
摘要:详见代码:#include <cstdio>#include <cstring>#include <cstdlib>#define MOD 29using namespace std;/*求2004^x次方的所有因子对29取余,可能是由于这一年是闰年才选择的29 我们可以对2004进行分解 2004 = 2^2 * 3 * 167,很明显2^2 和 3 和 167 都是相互互质的因此就可以利用到一个数的因子和是一个积性函数这个性质,设S(N)为这个函数 又因为S(p^n) = 1+p+p^2+...+p^n,所以一个数被用素数的指数幂来表示的话就能够被分解化 阅读全文
posted @ 2012-12-31 22:55 沐阳 阅读(245) 评论(0) 推荐(0) 编辑
摘要:这题给定一个N,求最小的x^2满足y^2 = x^2 + N;将x^2移到左边,得到(y+x)*(y-x) = N,于是我们分解N成两个约数相乘的形式,于是我们从sqrt(N)到1开始枚举约数,得到可以相除的约数对(a, b)后,直接计算abs((a-b) / 2)就是x的值了,当然x不能为零,并且a,b的奇偶性要一致。代码如下:#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue&g 阅读全文
posted @ 2012-10-12 19:59 沐阳 阅读(354) 评论(0) 推荐(0) 编辑
摘要:对于一个数F,设F = p1^e1*p2^e2...*pn^en 那么[1-N]内与其互质的数和与D = p1*p2*...pn是一致的,因为和F、D互质的数都是不含有他们的素因子的数。对于D这个数求[1-N]内有多少个与其互质的数就可用运用容斥定理来求解了。以6为例,首先计算出与2不互质的数,用等差数列公式能够计算出这些满足于2不互质数的和,接着就加上与3不互质的和,最后再减一次与6不互质的和即可。对于那些改变的数,由于数量不是很多,可以单独拿出来进行处理。代码如下:#include<iostream>#include<cstdio>#include<cstdl 阅读全文
posted @ 2012-09-22 21:21 沐阳 阅读(740) 评论(1) 推荐(0) 编辑
摘要:将gg(n)视为一个未知元,先由1000000007找出循环节222222224,然后再找出g(n)为变量时的循环节183120,然后应用矩阵快速幂求解即可。代码如下:#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<set>#include<map>#include<cstring>#include<vector& 阅读全文
posted @ 2012-09-19 15:44 沐阳 阅读(279) 评论(0) 推荐(0) 编辑
摘要:求一个数形如 A^B 的所有因子和对9901的模。我们首先得到A的素因子分解形式p1^e1*p2^e2...pn^en 它的B次方就是p1^E1*p2^E2...pn^En,其中Ei = ei*B。其素因子的和就是(p1^0+p1^2+p1^3+...+p1^E1)*(p2^0+p2^2+p2^3+...+p2^E2)*... 对于其中的一项进行二分计算即可。注意大质数的存在。代码如下:#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include 阅读全文
posted @ 2012-09-13 12:15 沐阳 阅读(256) 评论(1) 推荐(0) 编辑
摘要:题意是给定一个大数,这个数是由两个素数相乘得到的,现在问你这个大数的分解是否存在一个素数小于给定的数。由于这个给定的数L小于10^6,所以我们就可以打表到10^6,最好打的大一点(比10^6大的最小的素数即可),这样可以方便跳出循环。接下来,对于每一个数,我们直接对其小于L的所有素数进行一次试除,看是否余数为零。这里用到了一个大数取模的运算,一个大数对一个int型的数。过程是这样的,我们可以把一个数(abc...xyz)看作是10*(abc...xy)+z --> 10*(10*(abc...x)+y)+z,一直这样下去,我们在从最里面取模开始即可。代码如下:#include <c 阅读全文
posted @ 2012-09-12 20:22 沐阳 阅读(378) 评论(0) 推荐(0) 编辑
摘要:给定一个数N,判定(1-N)中的数P满足gcd(N, P) != 1 && N % P != 0,当一个数在(1-N)中有奇数个这样的数,那么我们就是这个数是可取的,现在要求统计某一个区间[a,b]内有多少个满足要求的数。一般的思路就是通过区间相减来做了,对于1-N中有多少个这样的可以通过找规律来解决,不管你找没找到,我是没找到...这题可以来想,对于一个数N,其不互质的数的个数就是 N - phi(N),在剩余的数里面有多少个数是N的因子呢,通过素因子分解我们知道答案是T = (e1+1)*(e2+1)*...其中e1,e2是素因子的指数,所以最后结果就是 N-phi(N)- 阅读全文
posted @ 2012-09-11 11:47 沐阳 阅读(809) 评论(0) 推荐(1) 编辑
摘要:这一题是给定一个N,求一个最小的数M满足M^2%10^k = N,也就是M的平方的后面与N相同位数的数字的值为N。对于这一题,我的思路就是BFS搜索,对于每一位,假设出一个数来使得其平方的结果逐步的逼近最终的结果。代码如下:#include <iostream>#include <cstdlib>#include <cstdio>#include <queue>#include <algorithm>using namespace std;// 假设N是一个5位数,那么最差情况时是由1个大于等于5位数的数的平方得到的// 否则的话,就 阅读全文
posted @ 2012-09-10 14:26 沐阳 阅读(318) 评论(0) 推荐(0) 编辑
摘要:这题如果是要输出所有的解的情况的话,用两个有序表查找可以优化到O(n^3),幸好这题只是要求出一种方案,那么我们就有以下结论:当 N < 8 的时候是无解的当 N > 8 并且 N是一个奇数的话,那么就可以拆成 2 + 5 + 一个偶数,根据哥德巴赫猜想,一个合数一定能够分解成两个素数之和,所以只要遍历一遍素数表即可当 N > 8 并且 N是一个偶数的话,那么就可以拆成 2 + 2 + 一个偶数,同理可以在 O (n / ln(n))的时间内完成。代码如下:#include <cstdlib>#include <cstdio>#include < 阅读全文
posted @ 2012-08-19 22:50 沐阳 阅读(319) 评论(0) 推荐(0) 编辑
摘要:这题是定义如下的一个数:S(0, 0) = 1; S(n, 0) = 0 for n > 0;S(0, m) = 0 for m > 0;S(n, m) = m S(n - 1, m) + S(n - 1, m - 1), for n, m > 0.也就是题中所说的把一个含有n个元素的集合分成m份,共有多少种分法。现在题目就是要求S(n, m)的奇偶性。如果m是一个偶数的话,那么我们可以推出 S(n, m)Ξ S(n-1, m-1) (mod 2),如果m是一个奇数的话,我们推出S(n, m)Ξ (S(n-1, m) + S(n-1, m-1)) (mod 2)。后面看到某一 阅读全文
posted @ 2012-08-10 23:03 沐阳 阅读(607) 评论(0) 推荐(0) 编辑
摘要:详见代码:方法一:#include <cstdlib>#include <cstring>#include <cstdio>using namespace std;char s[1005];int len, Mp[25] = {1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2};// 直接计算出其循环节为20这里将0-19的列表于上,当N<5时直接输出,其余需要递归N/5因为这个表是删除了所有的5的倍数的 int slove(){ int ans = 1; while (len) { len -= !s[len-1]; a 阅读全文
posted @ 2012-08-10 11:24 沐阳 阅读(1450) 评论(0) 推荐(0) 编辑
摘要:这个是参考了别人之后的代码,POJ上0MS过了。Orz......对于一个序列在提取了2,5之后,例如1,2,3,4,5,6,7,8,9,10,我们可以将其中的奇数和偶数分开来对待,对于偶数序列2,4,6,8,10由于原序列会被提取出2,所以就退化成了1,2,3,4,5,这个奇数序列,对于奇数序列1,3,5,7,9我们就可以来统计3,5,7的数量了,同样出现的次数是总长度N=10除以10(单位出现区间)再判定N%10是否大于要求得数,对于这个奇数序列由于5是要被提取的,所以又变成了1这个序列,更多数可能更好看了。如此递归下去便行了。代码如下:#include <cstdlib>#i 阅读全文
posted @ 2012-08-09 11:08 沐阳 阅读(704) 评论(0) 推荐(0) 编辑

点击右上角即可分享
微信分享提示