51nod 算法马拉松4 B递归(YY)
函数f(n,m)
{
若n=1或m=1返回a[n][m];
返回f(n-1,m)异或f(n,m-1);
}
读入2<=n,m<=100
for i=2->100读入a[1][i]
for i=2->100读入a[i][1]
输出f(n,m)
发现当n,m较大时程序变得异常缓慢。
小b经过一番思考,很快解决了这个问题。
这时小c出现了,我将n,m都增加131072,你还能解决吗?
相对的,我会读入2->131172的所有a[1][i]和a[i][1]。
小b犯了难,所以来找你,你能帮帮他吗?
Input
第一行读入131171个正整数,表示i=2->131172的a[1][i](1<=a[1][i]<=1000000000)。 第二行读入131171个正整数,表示i=2->131172的a[i][1](1<=a[i][1]<=1000000000)。 第三行读入一个正整数Q(1<=Q<=10000),表示询问的次数。 接下来Q行,每行两个数n,m(2<=n,m<=100),表示每一组询问。
Output
Q行,每行为f(n+131072,m+131072)
Input示例
2 3 4 5 6 7 8 … 131171 131172 2 3 4 5 6 7 8 … 131171 131172 3 2 2 2 3 2 4
Output示例
0 0 131072
考虑一个点(0, 0)对某一个点(n, m)的贡献次数为C(c + m, n),所以这里在计算f(n, m)时,只要知道第一行和第一列的每个数贡献的次数是基奇数此还是偶数次,也就是计算C(n+m, m)是奇数还是偶数, 那么只要知道n!里的2的个数G(n),那么如果有G(n + m) = G(n) + G(m),此时这个组合数就是偶数,否则为奇数。
由于f(n, m) = f(n - 1, m) + f(n, m - 1),只要知道对于f(131074, 131074...131172)与f(131074...131172, 131074)的每个值就好了(其他的可以由这些推过来)
1 #pragma comment(linker, "/STACK:1677721600") 2 #include <map> 3 #include <set> 4 #include <stack> 5 #include <queue> 6 #include <cmath> 7 #include <ctime> 8 #include <bitset> 9 #include <vector> 10 #include <cstdio> 11 #include <cctype> 12 #include <cstring> 13 #include <cstdlib> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 #define INF 0x3f3f3f3f 18 #define inf (-((LL)1<<40)) 19 #define lson k<<1, L, (L + R)>>1 20 #define rson k<<1|1, ((L + R)>>1) + 1, R 21 #define mem0(a) memset(a,0,sizeof(a)) 22 #define mem1(a) memset(a,-1,sizeof(a)) 23 #define mem(a, b) memset(a, b, sizeof(a)) 24 #define FIN freopen("in.txt", "r", stdin) 25 #define FOUT freopen("out.txt", "w", stdout) 26 #define rep(i, a, b) for(int i = a; i <= b; i ++) 27 #define dec(i, a, b) for(int i = a; i >= b; i --) 28 29 //typedef __int64 LL; 30 typedef long long LL; 31 typedef pair<int, int> Pair; 32 const int MAXN = 500000 + 10; 33 const int MAXM = 110000; 34 const double eps = 1e-12; 35 LL MOD = 1000000007; 36 37 const int N = 140000; 38 const LL mod = 2; 39 40 int f[410000]; 41 int ans[110][110]; 42 int r[140000], c[140000]; 43 44 void init(int n) { 45 f[0] = f[1] = 0; 46 rep (i, 2, n) { 47 int num = 0, x = i; 48 while(x % 2 == 0) num++, x /= 2; 49 f[i] = f[i - 1] + num; 50 } 51 } 52 53 int judge(int n, int m) { 54 return f[n] == f[m] + f[n - m]; 55 } 56 57 int calc(int n, int m) { 58 int ans = 0; 59 rep (i, 2, m) ans ^= c[i] * judge(n - 2 + m - i, m - i); 60 rep (i, 2, n) ans ^= r[i] * judge(n - i + m - 2, m - 2); 61 return ans; 62 } 63 64 int main() 65 { 66 //FIN; 67 //FOUT; 68 init(400000); 69 rep (i, 2, 131172) scanf("%d", &c[i]); 70 rep (i, 2, 131172) scanf("%d", &r[i]); 71 rep (i, 131074, 131172) ans[2][i - 131072] = calc(131074, i); 72 rep (i, 131074, 131172) ans[i - 131072][2] = calc(i, 131074); 73 rep (i, 3, 100) { 74 rep (j, 3, 100) { 75 ans[i][j] = ans[i - 1][j] ^ ans[i][j - 1]; 76 } 77 } 78 int q, n, m; 79 cin >> q; 80 while(q --) { 81 scanf("%d %d", &n, &m); 82 printf("%d\n", ans[n][m]); 83 } 84 return 0; 85 }