codeforces Gym 100814 A、B、F、I
A题 先求出来这个数是第几大 阶乘求概率p 然后计算获得胜率的概率 常规解法把所有情况考虑一遍(跳1次,2次,3次……)要用到组合数 数可能太大了会爆的行不通
我们观察发现它有递推性质,从第二大开始获胜概率为Q1=p(直接跳到第一大)从第三大开始获胜概率为Q2=p*Q1(先跳到第二大)+p(直接跳到第一大)以此类推Q3=Q2*p+Q1*p+p
Q4=Q3*p+Q2*p+Q1*p+p 但是我们按照上面的递推式计算Qn时复杂度为O(n*n) 我们再改进一下Q2=Q1*(1+p),Q3=Q2*(1+p) ,Q4=Q3*(1+p)这样复杂度就为 O(n) 了
#include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <string> #include <queue> #include <map> #include <vector> using namespace std; const int maxn = 2e2+10; const int maxm = 1e6+10; const int inf = 0x3f3f3f3f; const double epx = 1e-10; typedef long long ll; int a[maxn],b[maxn],c[maxn]; double f[maxm]; int main() { int t,n; b[0]=1; for(int i=1;i<=9;i++) b[i]=b[i-1]*i; cin>>t; while(t--) { cin>>n; int cnt=0; while(n!=0) { c[++cnt]=n%10; a[n%10]++; n/=10; } reverse(c+1,c+cnt+1); int sum=0; for(int i=1;i<=cnt;i++) { for(int j=9;j>=0;j--) { if(a[j]>0) { if(j>c[i]) sum+=b[cnt-i]; else if(j==c[i]) { a[j]--; break; } } } } double p=1.0/b[cnt]; if(sum==0) f[0]=0; else { f[sum-1]=p; for(int i=sum-2; i>=0; i--) { f[i]=f[i+1]*p+f[i+1]; } } printf("%.9lf\n",f[0]); } }
B题 直接模拟 我写的是最暴力的那种。。。
#include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <string> #include <queue> #include <map> #include <vector> using namespace std; const int maxn= 2e2+10; const int maxm= 1e4+10; const int inf = 0x3f3f3f3f; typedef long long ll; int main() { int t,n,m; while(cin>>t) { while(t--) { char a[maxn][maxn]; char ans[maxn]; cin>>n>>m; char x,y; for(int i=1;i<=m;i++) { for(int j=1;j<=2*n;j++) { cin>>a[i][j]; } } for(int i=1;i<2*n;i=i+2) { int cnt1=0,cnt2=0,cnt3=0,cnt4=0; int flag=0; for(int j=1;j<=m;j++) { if(a[j][i+1]=='T') { ans[i/2+1]=a[j][i]; flag=1; break; } else { if(a[j][i]=='A') cnt1++; else if(a[j][i]=='B') cnt2++; else if(a[j][i]=='C') cnt3++; else if(a[j][i]=='D') cnt4++; } } if(flag==0) { if(cnt1>0&&cnt2>0&&cnt3>0) ans[i/2+1]='D'; else if(cnt1>0&&cnt2>0&&cnt4>0) ans[i/2+1]='C'; else if(cnt1>0&&cnt3>0&&cnt4>0) ans[i/2+1]='B'; else if(cnt2>0&&cnt3>0&&cnt4>0) ans[i/2+1]='A'; else ans[i/2+1]='?'; } } for(int i=1;i<=n-1;i++) printf("%c ",ans[i]); printf("%c\n",ans[n]); } } }
F题 水~~
#include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <string> #include <queue> #include <map> #include <vector> using namespace std; const int maxn= 1e3+10; const int maxm= 1e4+10; const int inf = 0x3f3f3f3f; typedef long long ll; int n,m; int a[maxn]; int main() { while(cin>>n) { int a,b; while(n--) { cin>>a>>b; if(a==b) printf("Square\n"); else printf("Rectangle\n"); } } }
I题 n比较小直接枚举组合情况 一位一位比较记录第一次和最后一次不同的位置,直接异或也可以
#include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <string> #include <queue> #include <map> #include <vector> using namespace std; const int maxn= 1e3+10; const int maxm= 1e4+10; const int inf = 0x3f3f3f3f; typedef long long ll; int n,m; int a[maxn]; int main() { int t; while(cin>>t) { while(t--) { cin>>n; for(int i=1; i<=n; i++) cin>>a[i]; sort(a+1,a+1+n); int ans=-1; for(int i=1; i<n; i++) { for(int j=i+1; j<=n; j++) { int num=0; int tempi=a[i],tempj=a[j]; int cnt=1; while(tempi!=0) { int ki=tempi&1; int kj=tempj&1; if(ki!=kj) { num++; } tempi=tempi>>1; tempj=tempj>>1; cnt++; } while(tempj!=0) { if(tempj&1) { num++; } tempj=tempj>>1; cnt++; } //printf("%d %d %d\n",a[i],a[j],num); ans=max(ans,num); } } cout<<ans<<endl; } } }