topcoder srm 546 div1 比赛小记

topcoder srm 546 div1 比赛小记
吐槽:
   1. 模电铁定要挂了... Oh...No...
   2. 一次挂两题,错过了升黄的大好机会.
250pt:
    定义一个数S的序列{A} = F(S) = if(i == 0) Ai = S; else if(Ai-1 % 2 == 0) Ai = Ai-1 /2 ; else Ai = Ai-1 - 1;
    给三个长整型 K,A,B (小于1,000,000,000,000,000,000). 请问在区间[A,B]中的所有S对应的所有F(S)中K出现了几次.
算法分析:
    用二进制的角度去思考就很简单了... 额外要注意K=0和K=1的情况. 我就是考虑了K=0而没有考虑K=1而挂掉的..
 1 #include<iostream>
 2  using  namespace std;
 3  long  long chk(unsigned  long  long A,  long  long B,  int v){
 4  //   cout<<(A>>v)<<" "<<(B>>v)<<endl;
 5     if((A>>v) == (B>>v)) {
 6      return B-A+1;
 7   }
 8  //   cout<<"chk: "<<(1LL<<v)<<endl;
 9     return 1LL<<v;
10 }
11  long  long cal( long  long A,  long  long B){
12    if(A > B)  return 0;
13    if(A==0 || A==1)  return B+1-A;
14    bool flag = A & 1;
15    int v = 0;
16    long  long ans = 0;
17    long  long At = A+1;
18    while(1){
19      if(!flag && At <= B) ans += chk(At,B,v);
20      if(A <= B) ans += chk(A,B,v) ;  else  break;
21    //   cout<<ans<<endl;
22      A <<=1; At<<=1; v++; 
23   }
24   cout<<"ans: "<<ans<<endl;
25    return ans;
26 }
27  class KleofasTail{
28    public :  long  long countGoodSequences( long  long K,  long  long A,  long  long B){
29     //  cout<<cal(K,B)<<" "<<cal(K,A-1)<<endl;
30       return cal(K,B) - cal(K,A-1);
31   }
32 };
33 
500pt:
    问满足大于A(A<1,000,000,000,000,000)的且digit1至少出现count1次,digit2至少出现count2次的最小的数是多少?
    (count1+count2<15,digit1,digit2<10)
算法分析:
    利用数位DP的思想,从右相左依次判断让前i位完全活动是否是可行方案,显然第一个可行方案就是答案,将“自由活动”的数位构造一下就可以了。我没有将digit1和digit2的大小排序,结果输出了次优解。
 1 #include<iostream>
 2 #include<cstring>
 3  using  namespace std;
 4 typedef  long  long ll;
 5  int hash[11];
 6  bool fit( long  long N,  int a, int &c1,  int b,  int &c2){
 7      // cout<<N<<" ";
 8       while(N){
 9         ll x = N % 10;
10          if(x == a && c1) c1--;
11          if(x == b && c2) c2--;
12         N /= 10;
13     }
14      return  !c1 && !c2;
15 }
16 ll cal( int a, int c1, int b, int c2){
17     cout<<"cal: "<<a<<" "<<c1<<" "<<b<<" "<<c2<<endl;
18      int n = c1+c2; ll ans = 0;
19      for( int i=0; i < n; i++){
20         ans *= 10;
21          if(c1){
22             ans += a;
23             c1 --;
24         }
25          else {
26             ans += b;
27             c2 --;
28         }
29     }
30      return ans;
31 }
32  class FavouriteDigits{
33      public :  long  long findNext( long  long N,  int digit1,  int count1,  int digit2,  int count2){
34          if(digit1 > digit2){ swap(digit1,digit2); swap(count1,count2); }
35          int cnt1 = count1, cnt2 = count2;
36         ll  base[20];
37          base[0] = 1;
38          for( int i=1;i<20;i++)  base[i] =  base[i-1] * 10;
39          if(fit(N,digit1,cnt1,digit2,cnt2))  return N;
40          int flag = 0;
41          while(1){
42             ll D = N%10;
43             cnt1 = count1, cnt2 = count2;    
44             ll M = N+1;
45             fit(M,digit1,cnt1,digit2,cnt2);
46              if(flag >= cnt1+cnt2)  return M* base[flag] + cal(digit1,cnt1,digit2,cnt2);
47             cnt1 = count1, cnt2 = count2;
48              if(D < digit1){    
49                 M = N/10*10 + digit1;
50                 fit(M,digit1,cnt1,digit2,cnt2);
51                  if(flag >= cnt1+cnt2)  return M* base[flag] + cal(digit1,cnt1,digit2,cnt2);
52             }
53             cnt1 = count1, cnt2 = count2;
54              if(D < digit2){
55                 M = N/10*10 + digit2;
56                 fit(M,digit1,cnt1,digit2,cnt2);
57                  if(flag >= cnt1+cnt2)  return M* base[flag] + cal(digit1,cnt1,digit2,cnt2);
58             }
59             N/=10; flag ++;
60         }
61     }
62 };

你可能感兴趣的:(topcoder srm 546 div1 比赛小记)