hdu--4407--一不留神就TLE了

相比于上次我做过的一个容斥题 和他很相似 就是多了一个modify操作

不过也不难 只要 通过 加加减减 操作就能完成了

这个操作 我想过很多种方法 最后觉得用Map迭代访问是最好的选择

如果遍历x->y这个区间 因为y<=400000可能会太大

如果我记录操作1之前执行了多少次的操作2  然后来访问这些操作2  但是可能同一个位置上的数据被多次修改 这样统计也会出错

这边 使用map还有一个原因 就是操作总共也就1000次 那么我最差的情况也就是修改了999次 询问了1次 那map里面最多也就是插入了999个元素 很快的

------

然后我的tle也是发生在了map身上  还是我自己的思维不好 这个加加减减操作被我搞复杂了 后来去看了别人的 瞬间 fml

 1 void modify( LL x , LL y , LL p )
 2 {
 3     LL a , b c , d;
 4     map<LL,LL>::iterator it;
 5     for( it=mp.begin();it!=mp.end();it++ )
 6     {
 7         c = it->first;
 8         d = it-second;
 9         a = gcd( c , p );
10         b = gcd( d , p );
11         if( it->first == it->second || it->first<=x-1 || it->first >y )
12         {
13             continue;
14         }
15         else if( a==1 )
16         {
17             if( b==1 )
18                 ans = ans - c + d;
19             else
20                 ans = ans - c;
21         }
22         else
23         {
24             if( b==1 )
25                 ans = ans + d;
26         }
27     }
28 }
 1 void modify( LL x , LL y , LL p )
 2 {
 3     map<LL,LL>::iterator it;
 4     for( it=mp.begin();it!=mp.end();it++ )
 5     {
 6         if( it->first == it->second || it->first<=x-1 || it->first >y )
 7         {
 8             continue;
 9         }
10         if( gcd(it->first,p)==1 )
11             ans-=it->first;
12         if( gcd(it->second,p)==1 )
13             ans+=it->second;
14     }
15 }

第一个 罗里吧嗦的版本就是我写的 真TM 又臭又长啊  害我TLE了

  1 #include <iostream>
  2 #include <map>
  3 #include <vector>
  4 using namespace std;
  5
  6 typedef long long LL;
  7 LL ans;
  8 vector<int> ve;
  9 map<LL,LL>mp;
 10 void getPrime( int n )
 11 {
 12     for( int i = 2 ; i<=n/i ; i++ )
 13     {
 14         if( n%i==0 )
 15         {
 16             ve.push_back( i );
 17             while( n%i==0 )
 18                 n /= i;
 19         }
 20     }
 21     if( n>1 )
 22         ve.push_back( n );
 23 }
 24
 25 LL gcd( LL x , LL y )
 26 {
 27     return x % y == 0 ? y : gcd( y , x%y );
 28 }
 29
 30 LL solve( LL x )
 31 {
 32     LL ans = 0 , var , num;
 33     int veSize = ve.size() , cnt;
 34     for( int i = 1 ; i<( 1<<veSize ) ; i++ )
 35     {
 36         var = 1;
 37         cnt = 0;
 38         for( int j = 0 ; j<veSize ; j++ )
 39         {
 40             if( i&(1<<j) )
 41             {
 42                 var = (LL) (var * ve[j]);
 43                 ++ cnt;
 44             }
 45         }
 46         num = x / var;
 47         if( cnt&1 )
 48             ans += num * ( var + num * var ) / 2;
 49         else
 50             ans -= num * ( var + num * var ) / 2;
 51     }
 52     return ans;
 53 }
 54
 55 void modify( LL x , LL y , LL p )
 56 {
 57     map<LL,LL>::iterator it;
 58     for( it=mp.begin();it!=mp.end();it++ )
 59     {
 60         if( it->first == it->second || it->first<=x-1 || it->first >y )
 61         {
 62             continue;
 63         }
 64         if( gcd(it->first,p)==1 )
 65             ans-=it->first;
 66         if( gcd(it->second,p)==1 )
 67             ans+=it->second;
 68     }
 69 }
 70
 71 int main()
 72 {
 73     cin.sync_with_stdio(false);
 74     int t , n , m , op;
 75     LL x , y , p , c , ans1 , ans2 , sum1 , sum2;
 76     cin >> t;
 77     while( t-- )
 78     {
 79         cin >> n >> m;
 80         mp.clear();
 81         while( m-- )
 82         {
 83             cin >> op;
 84             if( op==1 )
 85             {
 86                 cin >> x >> y >> p;
 87                 ve.clear( );
 88                 getPrime( p );
 89                 sum1 = (x-1) * x / 2;
 90                 ans1 = solve( x-1 );
 91                 sum2 = y * (y+1) / 2;
 92                 ans2 = solve( y );
 93                 ans = sum2 - ans2 - ( sum1 - ans1 );
 94                 modify( x , y , p );
 95                 cout << ans << endl;
 96             }
 97             else
 98             {
 99                 cin >> x >> c;
100                 mp[x] = c;
101             }
102         }
103     }
104     return 0;
105 }

这种题目 还有一个很烦的地方就是 要用到long long或者__int64来处理

today:

  对于 性格 外向的女生 毫无 招架之力

时间: 2024-10-08 10:35:48

hdu--4407--一不留神就TLE了的相关文章

hdu 4407 Sum(容斥)

http://acm.hdu.edu.cn/showproblem.php?pid=4407 起初有n个数1~n,这里有m个操作,两种类型.操作1:求出[x,y]区间内与p互质的数的和.操作2:将第x位置的数变成y.对于每一个询问,输出结果. 因为只有1000次操作,而且起初是有序的.那么对于第i个询问,我们先忽略i之前的所有的第2种操作,即认为n个数为1~n,根据容斥原理求出[x,y]区间内与p互质的数之和,然后遍历i之前的操作2,对所求的答案进行调整即可.wa了无数次,改了好久,是因为我忽略

hdu 4407 Sum

http://acm.hdu.edu.cn/showproblem.php?pid=4407 题意:给定初始n个数1..n,两个操作,①1 x y p  询问第x个数到第y个数中与p互质的数的和; ②:2 x y  把第x个数变成y: 思路: 把p分解质因子,然后找出(1,pos)内与p不互质的,然后用的减去就是互质的和,第二个操作用到map映射,记录在那个位置改变之后的数. 1 #include <cstdio> 2 #include <cstring> 3 #include &

[容斥原理] hdu 4407 Sum

题意: 有两种操作1,2 1:询问 x,y区间能与p互质的数的和 2:将x改成p 一开始给N,初始是1~N个数 思路: 我们在求不互质的数有多少个的时候 其实就可以用等差数列求和求出这些数的和 那么我们到时候直接求一下就好了 然后因为这里的操作次数很少 所以我们可以标记一下哪些位置被修改过 然后在1操作的时候 特判一下这些位置 代码: #include"cstdlib" #include"cstdio" #include"cstring" #in

HDU 4407

这题不难吧,如果正在做组合的题... 使用容斥原理求解出(1~x)的与p互素的和,这是很容易的,很明显,首先要把p分解质因数. 而对于第二个操作,记录下他的转换的顺序,当要执行第一个操作时,遍历一次记录下的操作转换就可以了. 呃,这题虽然想到,但是,我的WA.看了网上的,思路和我的一样,我自己COPY别人的代码下来对拍数据,无误..但就是过不了.能想到的边界数据也试过了,还是过不了..求各路大神指错. 我的代码: #include <iostream> #include <algorit

hdu 4407 Sum 容斥+离线

求X-Y之间和p互质的数的和,典型的容斥问题,求和用等差数列求和,注意首项末项是多少. 首先记录下不修改的答案,离线处理,存下询问,输出的时候,遇到一个操作1,就遍历前面的操作,把修改加上去,注意要判重,只保留最后一次修改. #include <stdio.h> #include <vector> #include <algorithm> #include <cmath> #include <iostream> #include<cstri

ACM 容斥原理

VJ 点击打开链接 参考 点击打开链接 非常好的译文:点击打开链接 容斥原理的想法就是求多个集合的并集.所以要先设计好集合. 组合数学问题中,正面解决会困难,常用方法是正难则反,使用容斥原理求反向在用全集减去.将对立面的限制条件分析清楚. eg 求区间互质的数的个数,则用除法等计算出一个数的倍数的方法再减去. UVa 11806 Cheerleaders 求k个石子放在n*m的矩阵里 并且第一行 最后一行 第一列 最后一列都要有石子 考虑反面 求出所有的 减去不满足的情况 容斥原理总共4个 集合

HDU 1001(TLE代码)★留着待修改★

1 #include <stdio.h> 2 #include <math.h> 3 struct node{ 4 double x,y; 5 }point[100000]; 6 struct node nod; 7 int n=0,i=0; 8 int sort(void){ //选择排序:从小到大 9 int j,k; 10 for(i=0;i<n;i++){ 11 nod.x=point[i].x; 12 nod.y=point[i].y; 13 k=i; 14 for

hdu 3068 最长回文子串 TLE

后缀数组+RMQ是O(nlogn)的,会TLE..... 标准解法好像是马拉车,O(n).... 1 #include "algorithm" 2 #include "cstdio" 3 #include "cstring" 4 using namespace std; 5 #define maxn 220020 6 7 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; 8 int rank[maxn],heigh

HDU 5313 Bipartite Graph (二分图着色,dp) TLE!!!

题意:Soda有一个$n$个点$m$条边的二分图, 他想要通过加边使得这张图变成一个边数最多的完全二分图. 于是他想要知道他最多能够新加多少条边. 注意重边是不允许的. 思路:二分图着色这个简单,主要是dp,还有时间限制.我觉得应该是找出所有连通分量,每个连通分量两边的点数存起来,后面统一进行DP.但是!!时间仅有1s,而且还100个例子,就是说大概要在100万的复杂度才行,可是有1万个点,当m=5000时,这就不行. 我不懂这道题如何下手才能保证一定正确且不超时,应该优化得很厉害~ 贴一个我认

HDU 3572【最大流+数组开小会TLE】

题意:有M个机器,有N个任务.每个任务必须在Si 或者以后开始做,在Ei 或者之前完成,完成任务必须处理Pi 个时间单位.其中,每个任务可以在任意(空闲)机器上工作,每个机器的同一时刻只能工作一个任务,每个任务在同一时刻只能被一个机器工作,而且任务做到一半可以打断,拿去其他机器做.能否在规定时间内把任务做完. 这个题建图简直是经典..刚开始看也是一脸懵逼,还想用贪心搞一搞..但素感觉做不出来. 正确的思路是用网络流最大流. S与每个任务连边,容量为p,每个任务与相应的时间段连边,容量为1,每个时