【BestCoder】【Round#41】

枚举+组合数?+DP+数学问题


  http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=582

  QAQ许久没打过比赛,来一发BC,结果还是只能做前两题……too young too naive了……

  不过这场比赛前两题被hack&FST的人挺多的?蒟蒻手太慢,造数据也慢,玩不来hack……抢不到QAQ

A

  给5张牌,问最少换多少张可得到同花顺。

  其实是枚举花色,以及最小的是哪张(其实就是枚举换完以后,得到的是哪五张)看手里有多少张是已经得到的= =

  开个have[i][j]表示手里有花色为 i 数字为 j 的牌(其中,如果手里有A,那么1和14都置为true)

  hack点?没啥吧……可能有的同学是看手里连续拥有最大段是多长,比如手里最长的连续牌是123,那ans=2,但是135也是只需要换两张……

 1 //BestCoder #41 A
 2 #include<vector>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<iostream>
 7 #include<algorithm>
 8 #define rep(i,n) for(int i=0;i<n;++i)
 9 #define F(i,j,n) for(int i=j;i<=n;++i)
10 #define D(i,j,n) for(int i=j;i>=n;--i)
11 #define pb push_back
12 using namespace std;
13 inline int getint(){
14     int v=0,sign=1; char ch=getchar();
15     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
16     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
17     return v*sign;
18 }
19 const int N=1e5+10,INF=~0u>>2;
20 typedef long long LL;
21 /******************tamplate*********************/
22 
23 int a[6],b[6];
24 char s[6][10];
25 bool have[6][16];
26 int main(){
27 #ifndef ONLINE_JUDGE
28     freopen("A.in","r",stdin);
29     freopen("A.out","w",stdout);
30 #endif
31     int T=getint();
32     while(T--){
33         memset(have,0,sizeof have);
34         memset(a,0,sizeof a);
35         memset(b,0,sizeof b);
36         memset(s,0,sizeof s);
37         F(i,1,5) scanf("%s",s[i]);
38         F(i,1,5) a[i]=s[i][0]-'A';
39         F(i,1,5){
40             b[i]=s[i][1]-'0';
41             if (s[i][2]>0) b[i]=b[i]*10+s[i][2]-'0';
42             have[a[i]][b[i]]=1;
43             if (b[i]==1) have[a[i]][14]=1;
44         }
45 #ifdef debug
46         F(i,1,5) printf("%d %d\n",a[i],b[i]);
47 #endif
48         int ans=0;
49         rep(i,4){
50             int mx=0,now=0;
51             F(j,1,15){
52                 now=now+have[i][j]-have[i][max(j-5,0)];
53                 mx=max(mx,now);
54             }
55             ans=max(ans,mx);
56         }
57         printf("%d\n",5-ans);
58     }
59     return 0;
60 }
View Code

 

B

  一开始看错题了[捂脸熊]

  其实就是问有多少种情况下选出两个字符串你能赢。

  容易发现赢的情况是:两个字符串完全相同;或者两个字符串长度和为奇数。第一种情况只需一次B操作就赢了……第二种情况只要努力拿短的那个,最后一个肯定是你的。

  那么记录一下奇数长度和偶数长度的字符串有多少个,以及每个字符串有多少个与它相同(map大法吼!其实map存的是一个pair……first是key,second就是val)

  然后组合数算一下就好了。(然而蒟蒻在快结束的时候发现记录「有多少个奇/偶长度的字符串」的变量用的是int……而不是像ans一样用的是LL……感觉乘的时候要爆炸啊,果断重交了一发,分数&rank瞬间就下来了……QAQ(不过没有FST&被hack应该还是算赚了吧)

 1 //BestCoder #41 B
 2 #include<map>
 3 #include<string>
 4 #include<vector>
 5 #include<cstdio>
 6 #include<cstring>
 7 #include<cstdlib>
 8 #include<iostream>
 9 #include<algorithm>
10 #define rep(i,n) for(int i=0;i<n;++i)
11 #define F(i,j,n) for(int i=j;i<=n;++i)
12 #define D(i,j,n) for(int i=j;i>=n;--i)
13 #define pb push_back
14 using namespace std;
15 inline int getint(){
16     int v=0,sign=1; char ch=getchar();
17     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
18     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
19     return v*sign;
20 }
21 const int N=1e5+10,INF=~0u>>2;
22 typedef long long LL;
23 /******************tamplate*********************/
24 map<string,int>s;
25 LL gcd(LL a,LL b){return b ? gcd(b,a%b) : a;}
26 string s1;
27 int main(){
28 #ifndef ONLINE_JUDGE
29     freopen("B.in","r",stdin);
30     freopen("B.out","w",stdout);
31 #endif
32     int T=getint();
33     while(T--){
34         s.clear();
35         LL cnt0=0,cnt1=0;
36         LL n=getint();
37         F(i,1,n){
38             cin >>s1;
39             if (s1.length()&1) cnt1++;
40             else cnt0++;
41             if (s.find(s1)!=s.end()) s[s1]=s[s1]+1;
42             else s[s1]=1;
43         }
44         LL fz=(LL)cnt0*cnt1,fm=n*(n-1)/2;
45         for(map<string,int>::iterator it=s.begin();it!=s.end();it++){
46             LL v=it->second;
47             fz+=v*(v-1)/2;
48         }
49         LL d=gcd(fz,fm);
50         printf("%lld/%lld\n",fz/d,fm/d);
51     }
52     return 0;
53 }
View Code

 

C

  其实有一道题跟它是很相似的QAQ  【BZOJ】【3612】【HEOI 2014】平衡

  然而蒟蒻没有想到……

  并且这题卡空间!但是又由于有一些特殊性质,可以优化= =

  其实,每个数最多只能拆分成$O(\sqrt{n})$个数,因为有$\frac{x*(x+1)}{2}=n \rightarrow x=2*\sqrt{n}$

  所以其实在转移的时候,i-j 不会很远……所以之前很多的计算结果都不用保留了……所以?滚动数组!

 1 //BestCoder #41 C
 2 #include<cmath>
 3 #include<vector>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define rep(i,n) for(int i=0;i<n;++i)
10 #define F(i,j,n) for(int i=j;i<=n;++i)
11 #define D(i,j,n) for(int i=j;i>=n;--i)
12 #define pb push_back
13 using namespace std;
14 inline int getint(){
15     int v=0,sign=1; char ch=getchar();
16     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
17     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
18     return v*sign;
19 }
20 const int N=1e5+10,INF=~0u>>2,mod=998244353;
21 typedef long long LL;
22 /******************tamplate*********************/
23 int f[2000][640];
24 int main(){
25 #ifndef ONLINE_JUDGE
26     freopen("C.in","r",stdin);
27     freopen("C.out","w",stdout);
28 #endif
29     int T=getint(),n,c,l,r;
30     f[0][0]=1;
31     while(T--){
32         n=getint(); c=getint(); l=getint()-c; r=getint()-c;
33         LL ans=l==0; if (r==n) ans--;
34         F(i,1,r){
35             int now=i%1000;
36             memset(f[now],0,sizeof f[now]);
37             f[now][1]=1;
38             for(int j=2;j*(j+1)/2<=i;j++){
39                 int fa=now-j;
40                 if (fa<0) fa+=1000;
41                 f[now][j] = f[fa][j]+f[fa][j-1];
42                 if (f[now][j]>=mod) f[now][j]-=mod;
43             }
44             if (i>=l)
45                 for(int j=0;j*(j+1)/2<=i;j++){
46                     ans+=f[now][j];
47                     if (ans>=mod) ans-=mod;
48                 }
49         }
50         printf("%lld\n",ans);
51     }
52     return 0;
53 }
View Code

D

  SXBK的数学题>_>当然是果断弃疗啊……

  

posted @ 2015-05-17 11:34  Tunix  阅读(310)  评论(0编辑  收藏  举报