HDU 4407 Sum(容斥原理+质因数分解)
2015-08-24 17:29
337 查看
HDU 4407
题意:
给一个长度为n的序列,序列由1~n依次组成。对序列执行两种操作:
1.查询[x,y]内与p互素的数的和;
2.修改第x数为c.
思路:
往线段树的方向想了半天,发现就是容斥原理略微变形,脑残不可医啊。。修改操作可以用map进行映射。
查询操作的话我们就把序列一直当做1~n的序列来查询,然后迭代器跑一遍map判断对查询有无影响即可,总之操作最多2000次;
对于查询操作,我们可以先分解出p的质因数,设p的每种质因数组合的里的质因数乘积为value,那么[x,y]内value的倍数与p必定不互素,求出value的区间[x,y]内所有倍数和(用等比数列求和公式),然后对结果进行容斥求和,即得出区间[x,y]内与p不互素的数的和sum,然后区间所有数的和(用等差数列求和公式)减去sum即可。
代码:
[code]/* * @author FreeWifi_novicer * language : C++/C */ #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<string> #include<map> #include<set> #include<vector> #include<queue> using namespace std; #define clr( x , y ) memset(x,y,sizeof(x)) #define cls( x ) memset(x,0,sizeof(x)) #define mp make_pair #define pb push_back typedef long long lint; typedef long long ll; typedef long long LL; map<int , int>v ; vector<int>fac ; int gcd( int x , int y ){ if( y == 0 ) return x ; return gcd( y , x % y ) ; } lint cal( int l , int r , int val ){ int n = ( r / val ) - ( ( l - 1 ) / val ) ; int a1 = ( l % val == 0 )? l : ( val - l % val ) + l ; int an = r - r % val ; lint res = (lint)( a1 + an ) * (lint)n / 2 ; // 等比数列求和公式 return res ; } lint work( int l , int r , int p ){ fac.clear() ; for( int i = 2 ; i * i <= p ; i++ ){ if( p % i == 0 ){ fac.pb( i ) ; while( p % i == 0 ) p /= i ; } } if( p > 1 ) fac.pb( p ) ; int s = fac.size() ; lint res = 0 ; for( int i = 1 ; i < ( 1 << s ) ; i++ ){ int bits = 0 ; lint val = 1 ; for( lint j = 0 ; j < s ; j++ ){ if( i & ( 1 << j ) ){ bits++ ; val *= fac[j] ; } } lint tmp = cal( l , r , val ) ; if( bits & 1 ) // 容斥原理 res += tmp ; else res -= tmp ; } lint sum = (lint)( l + r ) * (lint)( r - l + 1 ) / 2 ; res = sum - res ; // 等差数列求和公式 return res ; } lint solve( int l , int r , int p ){ lint res = work( l , r , p ) ; if( v.empty() ) return res ; map<int,int>::iterator it ; for( it = v.begin() ; it != v.end() ; it++ ){ lint x = it->first , y = it->second ; if( x > r || x < l ) continue ; if( gcd( x , p ) == 1 ) res -= x ; if( gcd( y , p ) == 1 ) res += y ; } return res ; } int main(){ //freopen("input.txt","r",stdin); int t ; cin >> t ; while( t-- ){ v.clear() ; int n , m ; cin >> n >> m ; for( int i = 1 ; i <= m ; i++ ){ int op ; scanf( "%d" , &op ) ; if( op == 1 ){ int l , r , p ; scanf( "%d%d%d" , &l , &r , &p ) ; if( l > r ) swap( l , r ) ; lint ans = solve( l , r , p ) ; printf( "%I64d\n" , ans ) ; } else if( op == 2 ){ int pos , x ; scanf( "%d%d" , &pos , &x ) ; v[pos] = x ; } } } return 0; }
相关文章推荐
- POJ-1260-Pearls-动规
- 关于Flex 4&ActionScript 3和JavaScript的交互
- GDB使用指南
- Android4.4+ 外置SD卡不能写入 获取外置SD卡路径解决方案
- C# 工厂设计模式
- django模板变量直接显示html代码的问题
- iOS--开发文本输入框遇到的一些问题
- J-6 面向对象
- Nginx模块参考手册:HTTP核心模块
- centos(7.0) 上 crontab 计划任务
- POJ3122------Pie
- jquery中html、text、val的区别
- iOS7 Navgation的手势滑动返回功能
- 句号压缩过滤器
- 查询组列表时直接显示需要的组内成员
- BA-各大品牌性能对比
- 超链接中的href
- 错误总结
- 成都网站优化之企业网站内部优化
- 【转】【百度】 linux下单独编译安装Apache rewrite_module