51nod 算法马拉松4 B递归(YY)

递归

基准时间限制:1 秒 空间限制:131072 KB 分值: 80

函数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 }
时间: 2024-08-06 20:09:54

51nod 算法马拉松4 B递归(YY)的相关文章

随便玩玩系列之一:SPOJ-RNG+51nod 算法马拉松17F+51nod 1034 骨牌覆盖v3

先说说前面的SPOJ-RNG吧,题意就是给n个数,x1,x2,...,xn 每次可以生成[-x1,x1]范围的浮点数,把n次这种操作生成的数之和加起来,为s,求s在[A,B]内的概率 连续形的概率,想象为一个n维长方体,有两个平面与这个几何图形相割,于是就变成了求面(体)积问题,一般要去重,n维区域系数:s^n/n!,至于区间问题,直接前缀之差搞定 然后就是悲催的算法马拉松17F题了...其实是道好题来的,只是出题人不知世界上还有这题,然后某大牛把思路理清后把答案直接搬了过来 经典的1*2骨牌覆

51Nod 算法马拉松21(迎新年)

这次打算法马拉松是在星期五的晚上,发挥还算正常(废话,剩下的题都不会= =). 讲讲比赛经过吧. 8:00准时发题,拿到之后第一时间开始读. A配对,看上去像是二分图最大权匹配,一看范围吓傻了,先跳过读后面的题. B完全二叉树的方差,大概看了一遍,好神的样子,跳过. C多项式?好吧没学过FFT和NTT的我肯定不会,跳跳跳. D最大值,哎呦这函数什么破玩意儿,看不懂,跳跳跳. E B君的射击,卧槽毕克大人您出题就算了出这么一道码农题是要闹那样,跳跳跳. F那些年,我们一起讲的故事,卧槽这特么简直就

51Nod 算法马拉松15 记一次悲壮而又开心的骗分比赛

OwO 故事的起源大概是zcg前天发现51Nod晚上有场马拉松,然后他就很开心的过去打了 神奇的故事就开始了: 晚上的时候我当时貌似正在写线段树?然后看见zcg一脸激动告诉我第一题有九个点直接输出B就可以A.. 然后之后zcg以奇怪的二分方式发现了如何A掉第一题的第十个点(我记得貌似是什么第5000个数等于511? OwO 就这样没有任何思考含量全凭骗分黑科技过掉了第一题 OwO 然后zcg打开了第二题,发现第二题样例有点问题,然后就发了个帖子,直接去看第三题了 我去瞅了一眼,发现这不是gcd

51nod算法马拉松 contest7

A题 链接:http://www.51nod.com/contest/problem.html#!problemId=1417 推荐链接:http://blog.csdn.net/a837199685/article/details/45009337 设美女取得正面概率是p,反面就是(1-p),就是美女取一正一反和一反一正的概率相同,然后推出公式y=((a+b)/2+b)/(2*(a+b)); 1 #include<iostream> 2 #include<cstdio> 3 #i

51Nod 算法马拉松23 开黑记

惨啊--虽然开了半天黑,但是还是被dalao们踩了-- 第二次开黑,还是被卡在rank20了,我好菜啊--= = 写一写比赛经过吧-- 看到题之后习惯性都打开,A~D看上去似乎并没有什么思路,F应该是道数论题,看了E感觉有点意思,一看数据范围,咦怎么只有$50000$,再仔细看一看式子,手动分情况讨论之后得到一个结论-- 这题是水的线段树维护莫队啊= = 然后就开始码码码,由于一些脑残错误调了一会儿,然后就得到了这样的结果: 我坚信自己莫队的复杂度没错,然后就开始各种王逸松卡常,使用的卡常技巧包

51nod 算法马拉松4

http://www.51nod.com/contest/problemList.html#!contestId=9 D 装盒子 拓扑排序?

51NOD算法马拉松 最大值问题 离线预处理+set lower_bound

题目:http://www.51nod.com/contest/problem.html#!problemId=1349 题意:100000个数的序列,有100000次询问,每次问区间最大值大于等于k的区间有多少? 思路:一开始没看到"大于等于",想了很久也不会,原来看错题了.看错题害死人. 一般询问的问题,如果不能用线段树log(n)求出,那么就离线做. 首先将询问按从大到小排序,再将序列中的每个数排序,注意记录序号. 对于当前询问,每加进一个数,我需要找到它在加进的序列(按大小有序

51nod 算法马拉松35 E

有这样一段两两求最大公约数的程序CoGcd, int Gcd(int x, int y){ if(y == 0)return x; return Gcd(y, x % y); } void CoGcd(int m){ for(int i = 1; i <= m; i++) for(int j = 1; j <= m; j++) Gcd(i, j); } 给出m的值,进行t次询问,每次询问包含一对xi,yi.针对每次询问,输出整个程序执行过程当中,Gcd(xi, yi)被执行了多少次. 例如:\

51nod算法马拉松13

A 取余最长路 不难发现路径可以拆成三条线段,只要知道两个转折点的位置就能计算出答案. 设sum(i,l,r)表示第i行从l到r元素的和,则答案可以表示为sum(1,1,x)+sum(2,x,y)+sum(3,y,n)%p. 前缀和一下转化成(S3[n]-S3[y-1])+S2[y]+(S1[x]-S2[x-1])%p,从小到大枚举y,将所有(S1[x]-S2[x-1])扔到一个集合里,用个set就能轻松实现了. 时间复杂度为O(NlogN). #include<cstdio> #includ