Codeforces 818 E Card Game Again 线段树 思维
题目链接: http://codeforces.com/problemset/problem/818/E
题目描述: 给你N个数, 给你一个M, 问有多少个连续区间的乘积能整除M
解题思路: 我首先想的数处理前缀和, 但是这样就只能枚举两端点, O(n^2)肯定是T的, 这题看得题解.......题解用的是线段树, 存的是每一个区间的乘积, 每次查询查询的是当前区间的乘积, 需要得到的是离当前起点最近的连乘等于0的位置, 实际上我们在得到位置是二分得到的,我们枚举起点, 然后二分, 所以说复杂度是O(nlogn), 如果找到那个下标, 那么后面的所有数肯定都可以, 所以sum加一下就可以了。
代码:
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define mem0(a) memset(a,0,sizeof(a)) #define meminf(a) memset(a,0x3f,sizeof(a)) typedef long long ll; using namespace std; //const int INF = 0x3fffffff; const int maxn = 1e5 + 100; ll pro[maxn<<2]; ll arr[maxn]; int n, k; void pushup( int rt ) { pro[rt] = ( pro[rt<<1] % k * pro[rt<<1|1] % k ) % k; } void build( int l, int r, int rt ) { if( l == r ) { pro[rt] = arr[l] % k; return; } int m = (l + r) >> 1; build( lson ); build( rson ); pushup( rt ); } ll query( int L, int R, int l, int r, int rt ) { if( L <= l && r <= R ) { return pro[rt]; } int m = (l + r) >> 1; ll ret = 1; if( L <= m ) ret *= query(L, R, lson ) % k; if( R > m ) ret *= query(L, R, rson ) % k; return ret % k; } int main() { mem0( arr ); mem0( pro ); scanf( "%d%d", &n, &k ); for( int i = 1; i <= n; i++ ) { scanf( "%lld", arr+i ); } build( 1, n, 1 ); // for( int i = 1; i <= 10; i++ ) { // cout << pro[i] << " "; // } // cout << endl; ll sum = 0; for( int i = 1; i <= n; i++ ) { int l = i; int r = n; int pos = n; while( l < r ) { // 二分找到最左面的连乘是k的倍数的数 int mid = (l + r) >> 1; if( query(i, mid, 1, n, 1) % k == 0 ) { pos = mid; r = mid; } else { l = mid+1; } } if( query(i, pos, 1, n, 1) % k == 0 ) { // 有可能pos = n但是不可以整除, 这样判断一下就排除了这种情况 // cout << pos << endl; sum += n-pos+1; // 如果当前位可以整除 k 则乘上后面的数就都可以了, 所以方案数要加上后面的个数 } } printf( "%lld\n", sum ); return 0; }
思考: 其实自己也想过线段树来做, 只是线段的用处没有想好.....没有想到通过找那个下标来二分来减少复杂度, 自己做的题还是太少了
posted on 2017-08-17 14:49 FriskyPuppy 阅读(399) 评论(0) 编辑 收藏 举报