SRM555-DIV1

255point

题意:给你一段0、1组成的字符串,数出最少的5的倍数有多少。

做法:由题意范围,可知倍数的个数约有log(5, 2^50)(5为底) = 22个,因此预处理出所有满足5的倍数的字符串。

   dp[i]表示从左到右第i个数为止最少有多少个5的倍数的二进制串,枚举i->j中的每个点每次符合条件的,转移方程为:dp[i] = min(dp[j] + 1, dp[i]);

复杂度:(n-1)n/2+22; (n为字符串长度)

代码:

 1 class CuttingBitString{

 2 public:

 3     string *str;

 4     CuttingBitString() {

 5         str = new string[23];

 6         long long x = 5.1920929e15;

 7         int cnt = 0;

 8         stack<long long> q;

 9         for(long long i = 1; i <= x; i*=5) {

10             long long b = i;

11             while(b != 0) {

12                 q.push(b%2);

13                 b /= 2;

14             }

15             int xx = q.size();

16             while(!q.empty()) {

17                 str[cnt] += q.top()+'0';

18                 q.pop();

19             }

20             cnt++;

21         }

22     }

23     bool check(int l, int r, string s) {

24         while(l < r && s[l] == '0') l++;

25         string str2 = s.substr(l, r-l+1);

26         for(int i = 22; i >= 0; i--) {

27             if(str[i] == str2) return true;

28         }

29         return false;

30     }

31     int getmin(string S){

32         int dp[60];

33         int n = S.length(), ix;

34 

35         for(ix = 0; ix < n; ix ++) {

36             if(S[ix] != '0') break;

37         }if(ix == n) return -1;

38 

39         memset(dp, 0x7f, sizeof(dp));

40         dp[ix] = 1;

41         for(int i = ix+1; i < n; i++){

42             if(check(ix, i, S)) dp[i] = 1;

43             else {

44                 for(int j = ix; j < i; j++) {

45                     if(check(j+1, i, S)) {

46                         dp[i] = min(dp[j] + 1, dp[i]);

47                     }

48                 }

49             }

50         }

51         return dp[n-1];

52     }

53 

54 };
srm-555-1-233

 

555point

题意:H*W的矩阵初始矩阵内元素全为0,每次翻转为翻转一列/一行,翻转后该列/行全部元素原为0的变成1(反之则反),翻转Rcount次row,翻转Ccount次column,最后得到S个1.问实现这种翻转的方案数有多少。

做法:可知对于一行的奇数次翻转有效,设a、b为有效翻转row、column次数, 则 H*a + W*b - 2*a*b = S。

  枚举每个合法的a、b,则对于每个a、b方案数为C(H, a) * C(W, b) * C(H+(Rcount-a)/2-1, H-1) * C(W+(Ccount-b)/2-1, W-1),所有的方案数之和便是解。

复杂度:【预处理n^2/2】+ Rcount*Ccount

代码:

 1 class XorBoard {

 2 public:

 3     int count(int H, int W, int Rcount, int Ccount, int S) {

 4         for ( int i = 0; i <= 4000; i ++ ) 

 5             for ( int j = 0; j <= min( i, 2000 ); j ++ ) c[i][j] = ( j == 0 ) ? 1 : ( c[i - 1][j] + c[i - 1][j - 1] ) % mol;

 6 

 7 

 8         long long cnt = 0;

 9         for(int i = 0; i <= Rcount; i++ ) {

10             for(int j = 0; j <= Ccount; j++ ) {

11                 if(i * W + j * H - 2*j*i == S && (Rcount - i) % 2 == 0 && (Ccount - j) % 2 == 0 && i <= H && j <= W) {

12                     cnt = (cnt + c[H][i] * c[W][j] % mol * c[H+(Rcount-i)/2-1][(Rcount-i)/2] % mol * c[W+(Ccount-j)/2-1][(Ccount-j)/2] % mol) % mol;

13                 }

14             }

15         }    

16         return (int) cnt;

17     }

18 

19 };
srm-555-1-555

 

你可能感兴趣的:(div)