【分治】洛谷试炼场

P1226 【模板】快速幂||取余运算

 

快速幂板子题:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef unsigned long long ll;
 4 ll Mul ( ll a ,ll b , ll p ){
 5     a %= p;
 6     b %= p;
 7     ll c = (long double ) a*b / p;
 8     ll ans = a*b - c*p;
 9     if( ans < 0 ) ans += p ;
10     else if( ans >= p ) ans -= p ;
11     return ans ;
12 }
13 ll qmul( ll a , ll b , ll p ){
14     ll ans = 0;
15     a %= p ;
16     while ( b ){
17         if( b & 1 ){
18             ans = (ans + a)%p;
19         }
20         a =( a + a )%p;
21         b>>=1;
22     }
23     return ans ;
24 }
25 ll qpow ( ll a , ll b , ll mod ){
26     a %= mod ;
27     ll ans = 1 ;
28     while ( b ){
29         if( b & 1 ){
30             ans = qmul( ans , a , mod );
31         }
32         a = qmul(a,a,mod);
33         b >>= 1 ;
34     }
35     return ans % mod ;
36 }
37 int main()
38 {
39     ll a,b,p,ans;
40     cin >> a >> b >> p ;
41     ans = qpow(a,b,p);
42     cout<<a<<"^"<<b<<" mod "<<p<<"="<<ans<<endl;
43     return 0 ;
44 }
View Code

 


 

 

P1010 幂次方

【题解】

  用到的就是基础的dfs来做法来做,除非是 当前位置数位上的数是   1 或者 2 ,否则直接下一层,下一层进入之前应该外面套一个 “2 (” , 出来的时候,套回去 " ) "。 

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 void dfs( int x ){
 4     if( x == 0 ){
 5         printf("2(0)");
 6     }else if( x == 1 ){
 7         printf("2");
 8     }else{
 9         bool f = false ;
10         for( int i=14 ; i>=0 ; i-- ){
11             if( ( x & (1 << i) )   == (1 << i) ){
12                 if( f ) printf("+");
13                 else f = true;
14 
15                 if( i != 1 && i != 0 ){
16                     printf("2(");
17                     dfs( i ) ;
18                     printf(")");
19                 }else{
20                     dfs(i);
21                 }
22             }
23         }
24     }
25 }
26 int main()
27 {
28     int n;
29     scanf("%d",&n);
30     dfs(n);
31     puts("");
32     return 0;
33 }
View Code

 

 


 

 

P1908 逆序对

【题解】

【树状数组】

  用了两种方法来尝试,第一种就是树状数组,这个就不多说了,基本套路操作,就是离散化之后,维护每一个位置 上前一个有多少个桶,用目前现在的下标  - 对应前面的多少个桶的形式来计算该位置上的逆序数,其余也是这样。

 

【归并排序】

  利用归并排序来做,这个题目显得更加恰当。

  先分后治。

  主要在治的方面,两个已排序的数组,两个头指针指着的位置 设为 p1 , p2 。

  p1 < p2 :直接放即可

  p1 > p2 :  这时候就需要统计前面数组中,前一个数组剩余个数。

 

树状数组做法:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N = 5e5+100;
 5 
 6 ll c[N];
 7 
 8 typedef struct Node {
 9     int id , val ;
10 }Node ;
11 
12 bool cmp1 ( Node u , Node v ){
13     if( u.val == v.val ) return u.id < v.id ;
14     return u.val < v.val ;
15 }
16 bool cmp2 ( Node u , Node v ){
17     return u.id < v.id ;
18 }
19 
20 int lowbit( int x ){
21     return x & -x ;
22 }
23 
24 void update( int No , int val ){
25     while( No < N ){
26         c[No] += val ;
27         No += lowbit(No);
28     }
29 }
30 
31 ll getsum( int No ){
32     ll res = 0;
33     while( No > 0 ){
34         res += c[No];
35         No -= lowbit(No);
36     }
37     return res ;
38 }
39 Node a[N];
40 int main()
41 {
42     int n;
43     scanf("%d",&n);
44     for( int i = 1 ; i <= n; i++){
45         scanf("%d",&a[i].val);
46         a[i].id = i ;
47     }
48     sort( a+1 , a+1+n , cmp1 );
49     for( int i=1;i<=n;i++){
50         a[i].val = i ;
51     }
52     sort( a+1 , a+1+n , cmp2 );
53     ll ans = 0 ;
54     for( int i=1 ; i <= n ;i++ ){
55         ans += i - getsum(a[i].val)-1 ;
56         update( a[i].val , 1 );
57     }
58     printf("%lld\n",ans);
59     return 0 ;
60 }
View Code

 

归并排序做法:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N = 5e5+100;
 5 ll a[N],b[N];
 6 ll ans = 0 ;
 7 void Merge_sort( int L , int R ){
 8     if( L == R ) return ;
 9     int Mid = L + R >> 1 ;
10 
11     Merge_sort( L , Mid ) ;
12     Merge_sort( Mid+1 , R );
13 
14     int i = L , j = Mid + 1 , k = L ;
15     while( i <= Mid && j <= R ){
16         if( a[i] <= a[j] ){
17             b[k++] = a[i++];
18         }else{
19             b[k++] = a[j++];
20             ans += Mid - i + 1 ;
21         }
22     }
23     while( i <= Mid ) b[k++] = a[i++];
24     while( j <= R ) b[k++] = a[j++];
25     for( int i = L ; i <= R ; i++ ){
26         a[i] = b[i] ;
27     }
28 }
29 int main()
30 {
31     int n;
32     scanf("%d",&n);
33     for( int i=1 ;i<=n;i++){
34         scanf("%lld",&a[i]);
35     }
36     Merge_sort( 1 , n  );
37     printf("%lld\n",ans);
38     return 0;
39 }
View Code

 

 


 

 

P1498 南蛮图腾

 

【题解】

  当你找到规律,这个题目就是迎刃而解

  首先是创造出第一个处理,然后向右平移 , 向右下平移,然后就完成了。主要要倒着来。

 

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N = 2e3+500;
 5 int a[N>>1][N];
 6 int main()
 7 {
 8     int n;
 9     scanf("%d",&n);
10 
11     for( int i = 0 ; i < N>>1 ; i++ ){
12         for( int j = 0 ; j < N ; j++ ){
13             a[i][j] = ' ';
14         }
15     }
16 
17     int len = 4 ;
18     a[0][0] = a[1][1] = '/';
19     a[0][1] = a[0][2] = '_';
20     a[0][3] = a[1][2] = '\\';
21 
22     while( --n ){
23         for( int i = len/2 ; ~i ; i-- ){
24             for( int j = 0 ; j < len ; j ++ ){
25                 a[i][j+len] = a[i+len/2][j+len/2] = a[i][j];
26             }
27         }
28         len <<= 1 ;
29     }
30 
31     for( int i = len/2 -1  ; ~i ; i-- ){
32         for( int j = 0 ; j < len + (len-i) ; j ++ ){
33             printf("%c",a[i][j]);
34         }
35         puts("");
36     }
37     return 0 ;
38 }
View Code

 

posted @ 2019-09-09 08:50  Osea  阅读(405)  评论(0编辑  收藏  举报