吐槽:
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 };
posted on 2012-06-17 09:46
西月弦 阅读(406)
评论(0) 编辑 收藏 引用 所属分类:
比赛感言