小知识(2)同余/大数(入门)
处理大数可以用同余。
公式:
(a*b)%c = ((a%c)*(b%c))%c
(a+b)%c = ((a%c)+(b%c))%c
http://www.fjutacm.com/Problem.jsp?pid=2424
简单的同余,直接用就行了。
然后一般可以按位读入取模。
http://www.fjutacm.com/Problem.jsp?pid=2422
简单的按位读入取模。
#include<stdio.h> #include<string.h> int main() { int n,b,m,y; char a[1001]; int c[1001]; while(~scanf("%s %d",a,&b)) { m=strlen(a); y=(a[0]-'0')%b; c[0]=a[0]-'0'; for(int i=0;i<m-1;i++) { y=(c[i]*10+(a[i+1]-'0'))%b; c[i+1]=y; } printf("%d\n",y); } return 0; }
http://www.fjutacm.com/Problem.jsp?pid=2419
这个也不难。
http://www.fjutacm.com/Problem.jsp?pid=2473
这个......我第一次硬算t了,在大佬的嘲讽下知道了直接用公式。
#include<stdio.h> #include<algorithm> #include<math.h> using namespace std; int main() { long long n,m,y; while(~scanf("%lld%lld",&n,&m)) { double x=(n+sqrt(n*n-4*__gcd(n,m)*m))/2.0; y=x; if(x==y) printf("%lld %lld\n",n-y,y); else puts("No Solution"); } return 0; }
好的我承认我就是傻逼
更深入的还没有具体了解,先码一下(大数乘法):
- 模拟乘法:最简单的乘法竖式手算的累加型;
- 分治乘法:最简单的是Karatsuba乘法,一般化以后有Toom-Cook乘法;
- 快速傅里叶变换FFT:(为了避免精度问题,可以改用快速数论变换FNTT),时间复杂度O(N lgN lglgN)。具体可参照Schönhage–Strassen algorithm;
- 中国剩余定理:把每个数分解到一些互素的模上,然后每个同余方程对应乘起来就行;
- Furer’s algorithm:在渐进意义上FNTT还快的算法。
码题时间:http://poj.org/problem?id=1001(求高精度幂)