现在很少在这个博客上贴题解了,贴这个题是因为这道题的数据给的真的是太巧妙了,出题人费尽心机呀。先分析数据再给题面
1 < Sp2(n) < 7994. 线性素数筛的小于7994的质数有1007个
而进一步筛得平方素数刚好500整个,那个7994是有500推出来的吧 :)
测试组数也是500,询问第n个平方素数,n的上界也是500,这种巧合,只能说god knows the reason.
接着划分平方素数,由于每个划分数为1或2或3。不用动态规划也很很快出结果。
\
CZ_PROB1 - Summing to a Square Prime
\
SP2={p∣p:prime∧(∃x1,x2∈Z,p=x21+x22)} SP2={p∣p:prime∧(∃x1,x2∈Z,p=x12+x22)} is the set of all primes that can be represented as the sum of two squares. The function SP2(n) SP2(n) gives the n nth prime number from the set SP2 SP2. Now, given two integers n n ( 0<n<501 0<n<501) and k k ( 0<k<4 0<k<4), find p(SP2(n),k) p(SP2(n),k) where p(a,b) p(a,b) gives the number of unordered ways to sum to the given total ‘ a a’ with ‘ b b’ as its largest possible part. For example: p(5,2)=3 p(5,2)=3 (i.e. 2+2+1 2+2+1, 2+1+1+1 2+1+1+1, and 1+1+1+1+1 1+1+1+1+1). Here 5 5 is the total with 2 2 as its largest possible part.
Input
The first line gives the number of test cases T T followed by T T lines of integer pairs, n n and k k.
Constraints
- 0<T<501 0<T<501
- 0<n<501 0<n<501
- 1<SP2(n)<7994 1<SP2(n)<7994
- 0<k<4 0<k<4
Output
The p(SP2(n),k) p(SP2(n),k) for each n n and k k. Append a newline character to every test cases’ answer.
Example
Input:
3
2 2
3 2
5 3
Output:
3
7
85
\
\
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const int N = 7994, M = 89;
char v[N];
int p[1007];
int getPrime(int n) {
memset(v + 2, 1, sizeof v);
int cur = 0;
for (int i = 2; i <= n; ++i) {
if(v[i]) p[cur++] = i;
for (int j = 0; j < cur && (i * p[j] <= n); ++j) {
v[i * p[j]] = 0;
if(i % p[j] == 0) break;
}
}
return cur;
}
int work(int n, int k) {
if(k == 1) return 1;
int cnt2 = n >> 1;
if(k == 2) return cnt2 + 1;
int cnt3 = n / 3, res = 0;
for (int i = 1; i <= cnt3; i++)
res += (n - i * 3) / 2;
return 1 + cnt2 + cnt3 + res;
}
int main()
{
getPrime(N - 1); // 1007个素数 .x <= 89
int cnt = 0;
for (int i = 1; i <= M; ++i)
for (int j = i; j <= M; ++j) {
int tmp = i * i + j * j;
if(tmp < N && v[tmp]) p[++cnt] = tmp;
} //刚好500个,题目数据范围也是500,巧了啊
sort(p + 1, p + cnt + 1);
//for (int i = 1; i <= cnt; ++i) printf("%d%c", p[i], " \n"[i == cnt]);
int T;
scanf("%d", &T);
while(T--) {
int n, k;
scanf("%d%d", &n, &k);
printf("%d\n", work(p[n], k)); //k = 1, 2, 3
}
return 0;
}
其实这个spoj界面比较好看。