UVA 1404 - Prime k-tuple
题意:找出a-b之间有多少个素数k元组,并且最后一个元素减第一个元素为s
思路:先筛出sqrt的素数,然后对于每个区间,在用这些素数去筛出区间的素数,然后twopointer搞一下即可
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <vector> using namespace std; typedef long long ll; int t, a, b, k, s; vector<int> save; int pow_mod(int x, int k, int mod) { int ans = 1; while (k) { if (k&1) ans = (ll)ans * x % mod; x = (ll)x * x % mod; k >>= 1; } return ans; } bool mlrb(int x) { if (x == 1 || x == 0) return false; for (int i = 0; i < 15; i++) { int a = rand() % (x - 1) + 1; if (pow_mod(a, x - 1, x) != 1) return false; } return true; } const int N = 10000005; const int M = 100005; int prime[M], pn = 0, vis[N]; void getprime() { for (int i = 2; i < M; i++) { if (vis[i]) continue; prime[pn++] = i; for (ll j = (ll)i * i; j < M; j += i) vis[j] = 1; } } int main() { getprime(); int now = 0; for (int i = 0; i < M; i++) { if (prime[now] == i) { now++; continue; } vis[i] = 0; } scanf("%d", &t); while (t--) { scanf("%d%d%d%d", &a, &b, &k, &s); save.clear(); for (int i = 0; i < pn; i++) { if (prime[i] > b) break; int tmp = a / prime[i] * prime[i]; if (tmp < a) tmp += prime[i]; if (prime[i] == tmp) tmp += prime[i]; for (int j = tmp; j <= b; j += prime[i]) { vis[j - a] = 1; } } for (int i = a; i <= b; i++) { if (vis[i - a]) continue; save.push_back(i); } /*for (int i = a; i <= b; i++) { if (mlrb(i)) save.push_back(i); }*/ int n = save.size(); if (n == 0) { printf("0\n"); continue; } int pre = 0; int cnt = 0; int ans = 0; for (int i = 0; i < n; i++) { cnt++; if (cnt >= k || save[i] - save[pre] >= s) { if (cnt == k && save[i] - save[pre] == s) ans++; while (cnt >= k || save[i] - save[pre] >= s) { pre++; cnt--; } } } printf("%d\n", ans); int now = 0; for (int i = a; i <= b; i++) { if (i == save[now]) { now++; continue; } vis[i - a] = 0; } } return 0; }
时间: 2024-10-10 12:47:20