解题报告 之 HDU5475 An easy problem
2015-09-28 16:46
369 查看
解题报告 之 HDU5475 An easy problem
DescriptionOne day, a useless calculator was being built by Kuros. Let's assume that number X is showed on the screen of calculator. At first, X = 1. This calculator only supports two types of operation.
1. multiply X with a number.
2. divide X with a number which was multiplied before.
After each operation, please output the number X modulo M.
Input
The first line is an integer T(
),
indicating the number of test cases.
For each test case, the first line are two integers Q and M. Q is the number of operations and M is described above. (
)
The next Q lines, each line starts with an integer x indicating the type of operation.
if x is 1, an integer y is given, indicating the number to multiply. (
)
if x is 2, an integer n is given. The calculator will divide the number which is multiplied in the nth operation. (the nth operation must be a type 1 operation.)
It's guaranteed that in type 2 operation, there won't be two same n.
Output
For each test case, the first line, please output "Case #x:" and x is the id of the test cases starting from 1.
Then Q lines follow, each line please output an answer showed by the calculator.
Sample Input
1 10 1000000000 1 2 2 1 1 2 1 10 2 3 2 4 1 6 1 7 1 12 2 7
Sample Output
Case #1: 2 1 2 20 10 1 6 42 504 84
Source
2015 ACM/ICPC Asia Regional Shanghai Online
题目大意:有一个数X,初始状态为1。给出两种操作,操作1是在现有的数上乘上一个数 y,操作2是除以一个之前已经乘过的某个数。注意操作2绝不会除以一个乘过的数两次。要求每次操作后输出X % M 的值。注意有1e5次操作,0<=y<=1e9。
分析:首先注意题目的描述,只有输出的时候才取模,这里一定要看清楚,不然就是千年WA。很自然的想法是直接硬上,每次都维护一下X的值,不过很容易发现这是不现实的,因为根本存不下那么大的数……然后又会很自然的想到把X表示为乘数 ∏yi
。但是又很明显发现时间复杂度是超过的,因为查询次数1e5。
于是乎必须要有一个log级别的算法。于是乎我组大神机智的想到了线段树(其实我也想到了线段树但是没有理智的分析复杂度。。。)。具体思路是,因为操作数为1e5,那么最多有1e5个乘数,首先假设他们都是1。操作1更新对应的节点为yi,操作2更新对应的节点为1。再由于乘法和取模的可交换性。所以节点的value表示取模后的结果即可。(为什么不用线段树就不能直接存取模后的值,原因在于用了线段树之后,通过将yi变为1后重新乘一次,将除法转为乘法,解决了除法和取模的不可交换性。)
每次操作直接输出root的value即可。还有一个坑点在于叶结点赋值yi时也要取模,血的教训。
上代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> using namespace std; typedef long long ll; const int maxn = 1e5 + 10; ll tree[maxn * 4]; ll M, X = 1; void pushUp( int v ) { tree[v] = tree[v << 1] * tree[(v << 1) + 1] % M; } void built( int v, int l, int r ) { if(l == r) { tree[v] = 1; return; } int mid = (l + r) >> 1; built( v << 1, l, mid ); built( (v << 1) + 1, mid + 1, r ); pushUp( v ); } void update( int v, int l, int r, int idx, ll val ) { if(l == r) { tree[v] = val%M; return; } int mid = (l + r) >> 1; if(idx <= mid) { update( v << 1, l, mid, idx, val ); } else { update( (v << 1) + 1, mid + 1, r, idx, val ); } pushUp( v ); } int main() { int T; cin >> T; for(int kas = 1; kas <= T; kas++) { ll Q; X = 1; scanf( "%I64d %I64d", &Q, &M ); printf( "Case #%d:\n", kas ); built( 1, 1, Q ); for(int k = 1; k <= Q; k++) { ll opt, ind; scanf( "%I64d %I64d", &opt, &ind ); if(opt == 1) { update( 1, 1, Q, k, ind ); } if(opt == 2) { update( 1, 1, Q, ind, 1 ); } X = tree[1]; printf( "%I64d\n", X ); } } return 0; }
就是这样拉~~膜拜一下新队友叔叔,简直是思维大神,仰视之~
相关文章推荐
- 网络工程师必备知识:苹果MAC系统下使用USB转console线配置交换机的连接方法
- vs2010启动调试很慢
- ReactiveCocoa & MVVM 学习总结一
- java命名规则(转)
- 功放AUX接口解析
- 如何提升 service 等级,不被kill(整合)
- 图片GZip压缩后体积竟然变大了
- Js-利用js实现文本框默认获取输入焦点
- 那些不安全的库函数
- 面试练习题-100w个数中找出最大的100个数
- Remove Linked List Elements
- find中的-print0和xargs中-0
- HMAC-SHA1各语言版本实现
- \xe4\xb8\xad\xe6\x96\x87 phython 字符编码乱码问题
- ehcache.xml详解
- vs2010 cannot file the PDB file解决
- 百度前端笔试题整体(2013年及之前的)
- 【转载】Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- 01.0 SpringMVC4 的开发环境搭建
- 视图控制器 的生命周期