1 / 42

发散思维

发散思维. 2008 年 11 月 16 日 主讲 :赵冬雪. 个人简介. 赵冬雪 ( 假装透明 ) 2005 级计算机 5 班 2007 年加入 ACM 现属队伍 TJU_BUDDHA Email: zdx1110@gmail.com BBS ID: zhaodongxue. TOJ 2076 . The Drunk Jailer. 题目描述:

ova
Download Presentation

发散思维

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 发散思维 2008年11月16日 主讲 :赵冬雪

  2. 个人简介 • 赵冬雪(假装透明) • 2005级计算机5班 • 2007年加入ACM • 现属队伍TJU_BUDDHA • Email: zdx1110@gmail.com • BBS ID: zhaodongxue

  3. TOJ 2076 . The Drunk Jailer • 题目描述: • 监狱有n间牢房,看守喝醉了。首先,他打开所有的牢房。之后,他锁上序号为偶数的牢房(2,4,6……)。之后,对于序号为3的倍数的牢房,若牢房已锁则打开它;否则锁上它。……整个过程一共进行n次,最后看守回去睡觉。此时,如果牢房开着,犯人将逃跑。 • 问一共会跑掉多少个犯人?

  4. Sample Input 2 5 100 Sample Output 2 10

  5. 直觉想法——模拟 复杂度O(n^2) int n, ans; bool state[n +1]; /*0表示锁上,1表示打开*/ int i; for(i = 1; i <= n; i += i) { if(state[i] == 1) state[i] = 0; else state[i] = 1; } for(i = 1, ans = 0; i <= n; i ++) ans += state[i]; cout << ans << endl;

  6. 发散思维 • 每间牢房最后状态与它被访问过的次数有关 • 奇数次则牢房开着,偶数次则牢房锁上 • 所以,每间牢房最后状态只与它的因子数有关 • x = a * b 或者 x = a * a 其中 a <= x , b <= x • 只有平方数会被访问奇数次 • 只需求1~n的平方数 • 只需将n开根号取整 ans = (int)sqrt(n); • 复杂度 O( 1 ) ;

  7. TOJ 1445. Ants • 题目描述 • 横杆上有n只蚂蚁在爬,杆长为l。已知蚂蚁的初始位置,但不知道蚂蚁的初始方向。一旦蚂蚁到达杆尽头,它就会掉下去。若两只蚂蚁相撞,他们同时改变方向继续爬。所有蚂蚁速度都为1. • 求:最后一只蚂蚁掉下去的最迟时间和最早时间。

  8. Sample Input 2 10 3 2 6 7 214 7 11 12 7 13 176 23 191 Sample Output 4 8 38 207

  9. 思维转换 • 所有蚂蚁速度都一样 && 相撞之后转向 • 可以理解为: 两只蚂蚁相遇后继续按照原方向原速度爬行 • 计算每只蚂蚁掉下去所需的最大时间和最小时间——该蚂蚁与杆两端的距离

  10. int pos[n]; int big = small = 0; int x, y, tmp; for(i = 0; i < n; i ++) { x = pos[i]; y = l – pos[i]; if(x > y) {tmp = x; x = y; y = tmp;} if(x > small) small = x; if(y > big) big = y; } cout << small << “ ” << big << endl;

  11. TOJ 1065.   Factorial • 题目描述 • 给定N的值(1 ≤ N ≤ 1000 000 000 ) • 计算 N ! 末尾 0 的个数

  12. Sample Input 6 3 60 100 1024 23456 8735373 Sample Output 0 14 24 253 5861 2183837

  13. 题目分析 • 如果暴力计算,时间与空间都不允许 • 可以转而分析0出现的条件 • 2 * 5 = 10 • 转而计算2和5因子出现的次数 • 转而计算5出现的次数 • 5,10, 15, 20, 25, 30,35, 40…… • 需要注意:25, 50, 75, 100,125, ……

  14. 5……25……50……75……100……125 5 5 5 5 5 5 5 5 5 5 5 5 • ans = 0; • ans += n / 5; • ans += n / 25; • ans += n / 125; • ans += n / 625; • ……

  15. ans = 0; while(n) { ans += n / 5; n = n / 5; } cout << ans << endl;

  16. TOJ 3023.   Give Me an E • 数字的英文表示中,很多含有e • 给定一个n,计算第n个不含e的数字 • Note: 1,001,001,001,001,001,001,001,001,000 is "one octillion, one septillion, one sextillion, one quintillion, one quadrillion, one trillion, one billion, one million, one thousand" • 所有答案都小于1028

  17. Sample Input 1 10 838 0 Sample Output 2 44 4,002,064

  18. 含有e的数字 • one, two, three, four, five, • six, seven, eight, nine, ten, • eleven, twelve, thirteen, fourteen, fifteen, • sixteen, seventeen, eighteen, nineteen, • twenty, thirty, forty, fifty, sixty • seventy, eighty, ninety

  19. 1000以内不含e的数字 • 2 4 6 • 30 32 34 36 • 40 42 44 46 • 50 52 54 56 • 60 62 64 66 • 1000 • 共20个

  20. cnt = 0; while(n) { ans[cnt ++] = rem[n % 20]; n /= 20; } if(cnt > 7) { cnt = 10; ans[9] = ans[7]; ans[7] = ans[8] = 0; }

  21. if(cnt == 1) printf("%d\n", ans[0]); else { printf("%d", ans[cnt-1]); for(i = cnt-2; i >= 0; i --) printf(",%03d", ans[i]); printf("\n"); }

  22. TOJ 2852.   Bad Hair Day • 约翰大叔有N头牛,所有牛同向朝东站成一排 • 每头牛有一个固定身高 • 每头牛 i 能看见她前边的比她矮的牛的头顶,她共能看见 c [ i ] 头牛 • 求,c[1],c[2],……c[N]的总和

  23. Sample Input 6 10 3 7 4 12 2 Sample Output 5 Hint: 0 + 3 + 0 + 1 + 0 + 1 + 0 = 5

  24. 图示 = Cow#1 #2, 3, 4 = = Cow#2 = = = Cow#3 #4 = = = ---> Cow#4 = = = = = Cow#5 # 6 = = = = = = Cow#6 1 2 3 4 5 6

  25. 使用栈!! • 1 从最后一头牛开始,依次考虑每一头牛i • 2 如果她的身高比栈顶牛身高大,出栈。转2 • 3 如果她的身高不比栈顶牛身高大,计算两只牛标号的差,即为c[i]。该牛标号进栈。转1 • 4 所有c[i]的总和即为最后所求。

  26. sum = 0; top = 0; stack[top] = n-1; for(i = n-2; i >= 0;i --) { while(top>=0 && h[i] > h[stk[top]]){ top --;} if(top>=0)sum+=stack[top]-i-1; else sum+=n-1-i; top++; stk[top]=i; }

  27. 2440.   Bridge over a rough river • 题目描述 • N个人晚上过桥。桥只能承担两个人的重量。过桥必须携带手电筒。手电筒只有一个。一直每个人过桥所需的时间。若两个人同时过桥,他们所需的时间为较慢的人的时间。 • 问:N个人全部通过需要多少时间?

  28. Sample Input 4 6 7 6 5 Sample Output 29

  29. 传统想法:最快的人带着手电筒来回跑 • 分析其正确性: • N = 1, 2, 3, 正确 • N = 4,设他们过桥时间为a, b, X, Y 其中 a <= b <= X <= Y 总时间为a + a + b + X + Y • 是否可以更快呢?

  30. 消去X • 让X和Y一起过桥 • 所需时间为a + b + b + b + Y • 与上一结果a + a + b + X + Y比较 • 大小取决与 a + X 和 b + b 的大小,需讨论 • N > 4 ???

  31. 每次都将最慢的两个人送过桥 • 之后考虑剩下的N-2个人 • 直到N < 4 • N < 4 时分类讨论

  32. int f ( int n) { int res; if(n == 1) return t[0]; if(n == 2) return t[1]; if(n == 3) return t[0] + t[1] + t[2]; if(2 * t[1] > t[0] + t[n-2]) res = t[0] + t[0] + t[n-2] + t[n-1]; else res = t[0] + t[1] + t[1] + t[n-1]; res += f(n - 2); return res; }

  33. TOJ 1123.   Counterfeit Dollar • 题目描述 • Sally 有一打银币,但是只有其中的11枚是真的。假币的重量与真币不同,但是她并不知道假币是更轻还是更重。她借来一个天平,可以使用3次。已知3次的结果,问假币是哪一枚 • 题目保证结果唯一,银币用字母A~L表示

  34. Input: 1 ABCD EFGH even ABCI EFJK up ABIJ EFGH even Output: K is the counterfeit coin and it is light. 样例

  35. 题目分析 • 把case的形式全部转换成 even或up的形式(down可以转换成up,交换下天秤的左右) • 在上边的基础上,进行下边的讨论: • 满足以下两条件的字符,就是答案

  36. 条件一 • 情况1: 0个even 假币在天秤的同侧出现3次,也就是说这字符出现了3次 • 情况2: 1个even 假币在天秤的同侧出现2次,字符出现2次 • 情况3: 2个even 假币在天秤的同侧出现1次,字符出现1次 • 条件二:字符不出现在even的字串中

  37. TOJ 2959.   SREDNJI • 题目描述 • 数列A中有N个整数,分别为1~N • A的子串表示:只从A的头部和尾部删除x个数字(x可以是0)后所剩下的数列 • 数列A的中位数是B表示,在长度为奇数的数列A中,排序后B恰好在正中间。 • 已知数列长度N(1 ≤ N ≤ 100 000 )和数字B(1 ≤ B ≤ N ),求: • A有多少个子串的中位数是B?

  38. Sample Input #1 5 4 1 2 3 4 5 Sample Input #2 6 3 1 2 4 5 6 3 Sample Input #3 7 4 5 7 2 4 3 1 6 Sample Output #1 2 Sample Output #2 1 Sample Output #3 4 样例

  39. 序号 0 1 2 3 4 5 6 7 • 数值 5 7 2 4 3 1 6 • 大于 0 1 2 2 2 2 2 3 • 小于 0 0 0 1 1 2 3 3 • + • + + + • + + + + + • + + + + + + +

  40. 差 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 ----------------------------------------------------------------- 前 0 0 0 0 0 0 0 1 2 1 0 0 0 0 0 * 后 0 0 0 0 0 0 1 2 1 0 0 0 0 0 0 --------------------------------------------------------------- 积 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 变 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

  41. big[0] = sml[0] = 0; for(i = 1; i <= N; i ++){ big [i] = big [i-1]; sml [i] = sml [i-1]; if(a[i] < B) big[i] ++; else if(a[i] > B) sml [i] ++; } for(i = 0; i < q; i ++) bef[big[i] - sml [i] + N] ++; for(i = q; i <= N; i ++) aft[big[i] - sml [i] + N] ++; for(res = i = 0; i < 2 * N + 1; i ++) res += bef[i] * aft[i];

  42. 下课 Have Fun!!! o(∩_∩)o

More Related