HDU 6211 卡常数取模 预处理 数论
求所有不超过1e9的 primitive Pythagorean triple中第2大的数取模$2^k$作为下标,对应a[i]数组的和。
先上WIKI:https://en.wikipedia.org/wiki/Pythagorean_triple
里面有通过欧几里得公式来得到有关毕达哥拉斯式子的一些性质。
最后得到的一个关于互质的m,n变种的式子更加直观,因此枚举m,n,保证其合法。每次枚举n,筛掉和n有共同因子的m,范围是$\sqrt{1e9}$。然后由于要求的是b,而且取模的都是2的幂指,因此可以先预处理所有$b%(2^{17})$的个数,最后再模$(2^k) $即可。
但是用这个方法做这道题还会卡取模的常数,需要把取模换成$\&(2^{17} - 1)$
另一提,半夜两点和偶像在做同这题,人家是1A秒杀,而且代码很短,还是蛮高兴的,并不(。
/** @Date : 2017-09-17 23:49:14 * @FileName: HDU 6211 青岛网络1006 欧几里得 数论.cpp * @Platform: Windows * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : $Id$ */ #include <bits/stdc++.h> #define LL long long #define PII pair<int ,int> #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 32000; const double eps = 1e-8; int pri[N]; bool vis[N]; int c = 0; int prime() { MMF(vis); for(int i = 2; i < N; i++) { if(!vis[i]) pri[c++] = i; for(int j = 0; j < c && i * pri[j] < N; j++) { vis[i * pri[j]] = 1; if(i % pri[j] == 0) break; } } } LL coe[(1 << 17) + 20]; LL s[(1 << 17) + 20]; LL MA = (1LL<<17); int main() { int T; MMF(coe); prime(); //cout << c << endl; for(int i = 1; i * i <= 1000000000; i++) { MMF(vis); int t = i; for(int j = 0; j < c && pri[j] * pri[j] <= t; j++) { if(t % pri[j] == 0) { while(t % pri[j] == 0) t /= pri[j]; for(int k = pri[j]; k <= N; k+=pri[j]) if(!vis[k]) vis[k] = 1; } } if(t > 1) for(int k = t; k < N; k+=t) if(!vis[k]) vis[k] = 1; for(int j = i + 1; j * j + i * i <= 1000000000; j++) { if(!vis[j]/*__gcd(i, j) == 1*/ && !(j&1 && i&1)) { int a = 2 * i * j; int b = j * j - i * i; coe[max(a, b) & (MA - 1)]++; //ans += s[max(a, b) % MA]; } } //cout << ans << endl; } scanf("%d", &T); while(T--) { int n; scanf("%d", &n); LL ans = 0; int ma = (1 << n); for(int i = 0; i < ma; i++) scanf("%lld", s + i); for(int i = 0; i < MA; i++) ans += (LL)s[i & (ma - 1)] * coe[i]; printf("%lld\n", ans); } return 0; } /* 5 2 0 0 0 1 2 1 0 0 0 2 1 1 1 1 */ //https://en.wikipedia.org/wiki/Pythagorean_triple