数论(updating)

1、整除

“真”例题:洛谷3518

题解:首先结合裴蜀定理得出gcd(x,n)和gcd(x,y)均为密码,然后即可得出所有密码为x的1至n/x倍(x为gcd(a[k],n)的最小的不整除a[1]~a[k-1]的因子),因为因子数不多可以暴力筛选,ans=n/x。

 1 #include <bits/stdc++.h>
 2 #define int long long
 3 
 4 using namespace std;
 5 
 6 const int len = 3e5;
 7 int n,k,ans,a[len];
 8 
 9 inline bool cmp(int x) {
10     for (int i=1;i<k;i++) if (a[i]%x == 0) return false;
11     return true;
12 }
13 
14 signed main() {
15     ios :: sync_with_stdio(0);
16     cin >> n >> k;
17     for (int i=1;i<=k;i++) cin >> a[i];
18     a[k] = __gcd(a[k],n);
19     for (int i=1;i*i<=a[k];i++) {
20         if (a[k]%i==0 && cmp(i)) {
21             cout << n/i << endl;
22             return 0;
23         }
24         else if (a[k]%i==0 && cmp(a[k]/i)) {
25             ans = n/(a[k]/i);
26         }
27     }
28     cout << ans << endl;
29     return 0;
30 }

 2、真·同余线性筛素数

例题:poj3292

题解:变化版的线性筛

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int M = 1e6+11;
 8 int n,q,cnt;
 9 int h[M],s[M],p[M],ans[M];
10 
11 inline void pre_H() {
12     n = 0;
13     for (int i=5;i<=M;i++) {
14         if ((i-1)%4 == 0) h[++n] = i;
15     }
16     return;
17 }
18 
19 inline void init() {
20     cnt = 0;
21     for (int i=1;i<=n;i++) {
22         if (!s[h[i]]) s[h[i]] = 1,p[++cnt] = h[i];
23         for (int j=1;j<=cnt && h[i]*p[j]<M;j++) {
24             s[h[i]*p[j]] = s[h[i]]+1;
25             if (h[i]%p[j] == 0) break;
26         }
27     }
28     for (int i=5;i<M;i++) {
29         ans[i] = ans[i-1];
30         if (s[i] == 2) ans[i]++;
31     }
32     return;
33 }
34 
35 int main() {
36     pre_H();
37     init();
38     while (scanf("%d",&q) && q!=0) printf("%d %d\n",q,ans[q]);
39     return 0;
40 }

 3、同余

例题:洛谷1290

题解:找规律后可以发现,对于任意一种初始局面(即所需取数次数)不为1的情况先手有必胜策略(中间即使出现1先手也可以通过一定的取数策略达到此状态),故只需要考虑一开始连续为1的情况即可

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int c,n,m;
 6 
 7 int main() {
 8     ios :: sync_with_stdio(0);
 9     cin >> c;
10     while (c--) {
11         cin >> m >> n;
12         if (m < n) swap(m,n);
13         if (m%n == 0) {
14             cout << "Stan wins" << endl;
15             continue;
16         }
17         int f = 1;
18         while (m/n == 1) {
19             f = -f;
20             int k = n;
21             n = m%n,m = k;
22         }
23         if (f == 1) cout << "Stan wins" << endl;
24         else cout << "Ollie wins" << endl;
25     } 
26     return 0;
27 } 

 4、扩展欧几里得

例题:poj1061

题解:化出(m-n)x + Ly = y-x这个式子后直接大力exgcd

 1 #include <iostream> 
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define int long long
 6 
 7 using namespace std;
 8 
 9 int x,y,m,n,l,x_1,y_1;
10 int a,b,c,ans;
11 
12 inline int exgcd(int a,int b,int &x1,int &y1) {
13     if (!b) {
14         x1 = 1,y1 = 0;
15         return a;
16     }
17     int gcd = exgcd(b,a%b,x1,y1);
18     int tmp = y1;
19     y1 = x1-a/b*y1,x1 = tmp;
20     return gcd;
21 }
22 
23 inline void work() {
24     int ret = exgcd(a,b,x_1,y_1);
25     x_1 = x_1*c/ret;
26     int t = fabs(b/ret);
27     x_1 = (x_1%t+t)%t;
28 }
29 
30 signed main() {
31     cin >> x >> y >> m >> n >> l;
32     if (x == y) {
33         cout << 0 << endl;return 0;
34     }
35     a = m-n,b = l,c = y-x;
36     if (c%__gcd(a,b) != 0) cout << "Impossible" << endl;
37     else work(),cout << x_1 << endl;
38     return 0;
39 }

 5、pollard_rho

不说废话,上板子

 1 #include <bits/stdc++.h>
 2 #define int long long
 3 
 4 using namespace std;
 5 
 6 const int maxn = 10010;
 7 int n,cnt,f[maxn];
 8 
 9 inline int qm(int n,int m,int mo) {
10     int ans = 0;
11     while (m) {
12         if (m&1) ans = (ans+n)%mo;
13         m >>= 1,n = (n+n)%mo;
14     }
15     return ans;
16 }
17 
18 inline int qp(int n,int m,int mo) {
19     int ans = 1;
20     while (m) {
21         if (m&1) ans = qm(ans,n,mo);
22         m >>= 1,n = qm(n,n,mo);
23     }
24     return ans;
25 }
26 
27 inline bool mr(int n) {
28     for (int i=1;i<=10;i++) {
29         int a = rand()%(n-1)+1;
30         int m = n-1;
31         if (qp(a,m,n) != 1) return false;
32     }
33     return true;
34 }
35 
36 inline int pho(int n,int c) {
37     int i = 1,k = 2;
38     int x = rand()%(n-1)+1,y = x;
39     while (1) {
40         x = (qm(x,x,n)+c)%n;
41         int d = __gcd((y-x+n)%n,n);
42         if (d>1 && d<n) return d;
43         if (y == x) return n;
44         if (i == k) {
45             k <<= 1;
46             y = x;
47         }
48     } 
49 }
50 
51 inline void find(int n,int c) {
52     if (mr(n)) {
53         f[++cnt] = n;
54         return;
55     }
56     int p = n,k = c;
57     while (p >= n) p = pho(n,c--);
58     find(p,k),find(n/p,k);
59 }
60 
61 signed main() {
62     ios :: sync_with_stdio(0);
63     srand(time(NULL));
64     cnt = 0;
65     cin >> n;
66     find(n,1010);
67     sort(f+1,f+cnt+1);
68     for (int i=1;i<=cnt;i++) cout << f[i] << endl;
69     return 0;
70 }

 

posted @ 2018-05-07 22:47  LightOfDark  阅读(162)  评论(0)    收藏  举报