【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也是只需要换两张……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
B
一开始看错题了[捂脸熊]
其实就是问有多少种情况下选出两个字符串你能赢。
容易发现赢的情况是:两个字符串完全相同;或者两个字符串长度和为奇数。第一种情况只需一次B操作就赢了……第二种情况只要努力拿短的那个,最后一个肯定是你的。
那么记录一下奇数长度和偶数长度的字符串有多少个,以及每个字符串有多少个与它相同(map大法吼!其实map存的是一个pair……first是key,second就是val)
然后组合数算一下就好了。(然而蒟蒻在快结束的时候发现记录「有多少个奇/偶长度的字符串」的变量用的是int……而不是像ans一样用的是LL……感觉乘的时候要爆炸啊,果断重交了一发,分数&rank瞬间就下来了……QAQ(不过没有FST&被hack应该还是算赚了吧)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
C
其实有一道题跟它是很相似的QAQ 【BZOJ】【3612】【HEOI 2014】平衡
然而蒟蒻没有想到……
并且这题卡空间!但是又由于有一些特殊性质,可以优化= =
其实,每个数最多只能拆分成$O(\sqrt{n})$个数,因为有$\frac{x*(x+1)}{2}=n \rightarrow x=2*\sqrt{n}$
所以其实在转移的时候,i-j 不会很远……所以之前很多的计算结果都不用保留了……所以?滚动数组!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
D
SXBK的数学题>_>当然是果断弃疗啊……