http://www.bnuoj.com/bnuoj/contest_show.php?cid=3743#info
A
按照给定的表的顺序判断一下输出就可以了。。。
#include <iostream> #include <cstdio> using namespace std; int main(){ int T,x; scanf("%d",&T); while (T--){ scanf("%d", &x); if (x == 1 || x == 5 || x == 6) puts("Unknown"); else{ if(x==11 || x==12) puts("Basic Training"); if(x==12) puts("Rookie Contest"); if(x>=2 && x<=4) puts("Spring Training"); if(x==4) puts("BNU Contest"); if(x==7) puts("Practice Week"); if(x==7 || x==8) puts("Summer Training"); if(x>=9 && x<=11) puts("Regional Contest"); } } }
B
f[i][j] 表示i桶油能不能走j的距离
状态转移方程
f[i][j]=f[i][j]||f[i-1][j-a[s]];
#include <cstring> #include <cstdio> #include <iostream> using namespace std; int T,l,x,n; int f[5][1050]; int a[1050]; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d%d",&l,&x,&n); l-=x; for(int i=1;i<=n;i++) scanf("%d",&a[i]); if(l<0){ printf("No\n"); continue; } memset(f,0,sizeof(f)); f[0][0]=1; for(int s=1;s<=n;s++){ for(int i=1;i<=4;i++) for(int j=a[s];j<=l;j++){ f[i][j]=f[i][j]||f[i-1][j-a[s]]; } } if(f[4][l]==1) printf("Yes\n"); else printf("No\n"); } }
C 能被操作的次数就是L跟H能整除2的次数之和。判一下奇偶即可。
#include <cstring> #include <cstdio> #include <iostream> using namespace std; int T,l,x,n; int f[5][1050]; int a[1050]; int main(){ scanf("%d",&T); while(T--){ int L,H; scanf("%d%d",&L,&H); int sum=0; while(L%2==0) L/=2,sum++; while(H%2==0) H/=2,sum++; if(sum%2==0) puts("Adivon prevails"); else puts("Adidas loses"); } }
D
trie树 记录每个节点的个数与长度,dfs求解
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; int n,m; char a,b; int trie[200010][30],cnt[200010],sum[200010]; char c[100010]; int sz,ans; void insert(){ cout<<endl<<endl; int cur=0; int len=strlen(c); for(int i=0;i<len;i++){ //cout<<c[i]<<endl; cout<<cur<<endl; if(!trie[cur][c[i]-'a']){ trie[cur][c[i]-'a']=++sz; } sum[cur]+=len-i-1; cnt[cur]++;//////////// cur=trie[cur][c[i]-'a']; } //cout<<cur<<endl; } void init(){ memset(trie,0,sizeof(trie)); memset(cnt,0,sizeof(cnt)); memset(sum,0,sizeof(sum)); sz=0; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf(" %s",c); insert(); int len=strlen(c); for(int j=0,w=len-1;j<len/2;j++,w--){ char tmp; tmp=c[j]; c[j]=c[w]; c[w]=tmp; } insert(); } int ans=0; cout<<endl; for(int i=0;i<=sz;i++){ printf("%d %d\n",cnt[i],sum[i]); ans+=(cnt[i]-1)*sum[i]; } cout<<ans<<endl; } int main(){ int T; scanf("%d",&T); while(T--){ init(); } }
F
每一步期望获得的分数显然等于上一步获得分数加一,然后乘上概率p。最后将每一步期望的分数相加。
#include <cstdio> #include <iostream> using namespace std; int main(){ int T; scanf("%d",&T); while(T--){ int l; double p,tmp=0,ans=0; scanf("%d%lf",&l,&p); for(int i=1;i<=l;i++){ tmp=(tmp+1)*p; ans+=tmp; } printf("%.6lf\n",ans); } }
H 期望 1/(p*(1-p))
#include <iostream> #include <cstdio> using namespace std; int main(){ int T; scanf("%d",&T); while(T--){ double p; scanf("%lf",&p); printf("%.2lf\n",1/(p*(1-p))); } }
J f[i][0] 表示没用过忍术 f[i][1] 表示开始用第一次忍术 f[i][2] 表示结束了第一次忍术 f[i][3]开始用第二次忍术 f[i][4] 表示结束了第二次忍术
#include <cstdio> #include <iostream> using namespace std; int a[10010],c,n,f[10010][5]; int Max(int a,int b){ return a>b?a:b; } int main(){ scanf("%d%d",&c,&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); f[0][0]=c; f[0][1]=-0x7fffffff; f[0][2]=-0x7fffffff; f[0][3]=-0x7fffffff; f[0][4]=-0x7fffffff; for(int i=1;i<=n;i++){ f[i][0]=f[i-1][0]; if(f[i][0]-a[i]>=0) f[i][1]=Max(f[i-1][1],f[i][0]-a[i]); else f[i][1]=f[i-1][1]; f[i][2]=Max(f[i-1][2],f[i-1][1]+a[i]); if(f[i][2]-a[i]>=0) f[i][3]=Max(f[i-1][3],f[i][2]-a[i]); else f[i][3]=f[i-1][3]; f[i][4]=Max(f[i-1][4],f[i-1][3]+a[i]); } int ans=-0x7fffffff; for(int i=0;i<=4;i++){ ans=Max(ans,f[n][i]); } cout<<ans<<endl; }
k 矩阵快速幂优化一个递推关系。
递推关系如下。
#include <cstdio> #include <iostream> using namespace std; double f[1010*1010][21]; int main(){ int T; scanf("%d",&T); while(T--){ int n,m,k,s; scanf("%d%d%d%d",&n,&m,&k,&s); if(n==1){ printf("0.5000\n"); continue; } f[0][s]=1; for(int i=1;i<=m*k;i++){ for(int j=1;j<=n;j++){ if(j==1){ f[i][j]=f[i-1][2]*0.5; printf("%d %d %lf\n",i,j,f[i][j]); continue; } if(j==n){ f[i][j]=f[i-1][n-1]*0.5; printf("%d %d %lf\n",i,j,f[i][j]); continue; } if(j==2){ f[i][j]=f[i-1][1]+f[i-1][j+1]*0.5; printf("%d %d %lf\n",i,j,f[i][j]); continue; } if(j==n-1){ f[i][j]=f[i-1][n]+f[i-1][j-1]*0.5; printf("%d %d %lf\n",i,j,f[i][j]); continue; } f[i][j]=f[i-1][j-1]*0.5+f[i-1][j+1]*0.5; printf("%d %d %lf\n",i,j,f[i][j]); } } for(int i=1;i<=n;i++){ cout<<f[m*k][i]<<endl; } } }
矩阵优化如下
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #define SIZE 30 using namespace std; class MATRIX { public: double mt[SIZE][SIZE]; int x,y; friend MATRIX operator *(MATRIX &a,MATRIX &b){ MATRIX c; memset(c.mt,0,sizeof c.mt); c.x=a.x; c.y=b.y; for(int i=1;i<=a.x;i++) for(int j=1;j<=b.y;j++) for(int k=1;k<=a.y;k++) c.mt[i][j]=(c.mt[i][j]+(a.mt[i][k])*(b.mt[k][j])); return c; } friend void print(MATRIX &a){ cout<<a.x<<' '<<a.y<<endl; for(int i=1;i<=a.x;i++){ for(int j=1;j<=a.y;j++) printf("%.2lf ",a.mt[i][j]); printf("\n"); } } friend MATRIX power(MATRIX a, int b){ MATRIX ans; ans.x=a.x,ans.y=a.y; for(int i=1;i<=ans.x;i++) for(int j=1;j<=ans.y;j++){ if(i==j) ans.mt[i][j]=1; else ans.mt[i][j]=0; } for (; b; b >>= 1) { if (b & 1) ans = ans * a; a = a * a; } return ans; } }ans,M1,M; int n; int main() { int T; scanf("%d",&T); while(T--){ int n,m,k,s; scanf("%d%d%d%d",&n,&m,&k,&s); if(n==1){ printf("1.0000\n"); continue; } M1.x=M1.y=n; for(int i=1;i<=n;i++){ if(i==1){ M1.mt[1][2]=1; continue; } if(i==n){ M1.mt[n][n-1]=1; continue; } M1.mt[i][i+1]=M1.mt[i][i-1]=0.5; } M.x=1,M.y=n; M.mt[1][s]=1; ans=power(M1,m*k); ans=M*ans; for(int i=1;i<n;i++) printf("%.4lf ",ans.mt[1][i]); printf("%.4lf\n",ans.mt[1][n]); } }
I 折半查找 (待做。。
L 判断出直线与矩阵的交点分条件讨论(待做。