吐槽:
1. 模電鐵定要掛了... Oh...No...
2. 一次掛兩題,錯(cuò)過了升黃的大好機(jī)會(huì).
250pt:
定義一個(gè)數(shù)S的序列{A} = F(S) = if(i == 0) Ai = S; else if(Ai-1 % 2 == 0) Ai = Ai-1 /2 ; else Ai = Ai-1 - 1;
給三個(gè)長整型 K,A,B (小于1,000,000,000,000,000,000). 請(qǐng)問在區(qū)間[A,B]中的所有S對(duì)應(yīng)的所有F(S)中K出現(xiàn)了幾次.
算法分析:
用二進(jìn)制的角度去思考就很簡(jiǎn)單了... 額外要注意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至少出現(xiàn)count1次,digit2至少出現(xiàn)count2次的最小的數(shù)是多少?
(count1+count2<15,digit1,digit2<10)
算法分析:
利用數(shù)位DP的思想,從右相左依次判斷讓前i位完全活動(dòng)是否是可行方案,顯然第一個(gè)可行方案就是答案,將“自由活動(dòng)”的數(shù)位構(gòu)造一下就可以了。我沒有將digit1和digit2的大小排序,結(jié)果輸出了次優(yōu)解。
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 };
posted on 2012-06-17 09:46
西月弦 閱讀(417)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
比賽感言