2015 ACM Syrian Collegiate Programming Contest
A. My Friend of Misery
计算出答案的上下界即可。
时间复杂度O(n)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include<bits/stdc++.h> using namespace std; const int N=100010; typedef long long LL; int main(){ int _; scanf ( "%d" ,&_); while (_--){ int n; scanf ( "%d" ,&n); LL cur=0,r=1LL<<60; while (n--){ int x; char c; scanf ( "%d %c" ,&x,&c); if (c== '-' ){ r=min(r,cur+x+25); } else { cur+=x+25; } //printf("%lld\n",r-cur); } printf ( "%lld\n" ,r-cur); } } |
B. Brother Louie
纵坐标根据深度即可计算,比较麻烦的是横坐标。
设最左边的叶子的横坐标为t,那么每个点的横坐标都能表示为t+A_ir+B_ih,根据x_{root}=0,可以解出t,然后就可以计算出对应点的横坐标。
时间复杂度O(n)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include<cstdio> #include<algorithm> using namespace std; const int N=100010; int T,n,m,i,j,a[N],f[N],son[N][2],root; int d[N],cnt; double A[N],B[N]; //t+A*r+B*h void dfs( int x, int y){ d[x]=y; if (!a[x]){ A[x]=cnt*2; B[x]=cnt; cnt++; return ; } for ( int i=0;i<2;i++)dfs(son[x][i],y+1); A[x]=(A[son[x][0]]+A[son[x][1]])/2.0; B[x]=(B[son[x][0]]+B[son[x][1]])/2.0; } inline double askx( double r, double h, int x){ return (A[x]-A[root])*r+(B[x]-B[root])*h; } inline double asky( double r, double v, int x){ return -(r*2+v)*d[x]; } int main(){ scanf ( "%d" ,&T); while (T--){ scanf ( "%d%d" ,&n,&m); for (i=1;i<=n;i++){ scanf ( "%d" ,&a[i]); if (a[i]){ for (j=0;j<2;j++){ scanf ( "%d" ,&son[i][j]); f[son[i][j]]=i; } } } for (i=1;i<=n;i++) if (!f[i])root=i; dfs(root,0); while (m--){ double r,v,h; int x; scanf ( "%lf%lf%lf%d" ,&r,&v,&h,&x); printf ( "%.4f %.4f\n" ,askx(r,h,x),asky(r,v,x)); } root=cnt=0; for (i=0;i<=n;i++){ a[i]=f[i]=son[i][0]=son[i][1]=d[i]=0; A[i]=B[i]=0; } } return 0; } |
C. Everything
建立Trie树,dfs一遍得到每个串的字典序,然后枚举前缀,根据排名更新答案即可。
时间复杂度O(n\log n)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=100010,M=500010; int T,n,i,j,pos[N],rk[N],cnt,ans[N]; int tot,son[M][26],id[M],d[M],f[M]; int m,q[N],g[M],v[M],nxt[M],ed; char s[N]; inline bool cmp( int x, int y){ return rk[x]<rk[y];} inline void ins( int p){ scanf ( "%s" ,s); int l= strlen (s),x,i; for (x=0,i=0;i<l;i++){ int w=s[i]- 'a' ; if (!son[x][w]){ son[x][w]=++tot; f[tot]=x; } x=son[x][w]; } pos[p]=x; id[x]=p; } void dfs( int x, int y){ d[x]=y; if (id[x])rk[id[x]]=++cnt; for ( int i=0;i<26;i++) if (son[x][i])dfs(son[x][i],y+1); } inline void deal( int x){ for ( int i=pos[x];i;i=f[i]){ v[++ed]=x; nxt[ed]=g[i]; g[i]=ed; } } inline int cal( int n, int x){ return min(x,n-x+2); } inline void solve( int x){ m=0; for ( int i=g[x];i;i=nxt[i])q[++m]=v[i]; if (!m) return ; sort(q+1,q+m+1,cmp); for ( int i=1;i<=m;i++)ans[q[i]]=min(ans[q[i]],d[x]+cal(m,i)); } int main(){ scanf ( "%d" ,&T); while (T--){ scanf ( "%d" ,&n); for (i=1;i<=n;i++)ins(i); dfs(0,0); for (i=1;i<=n;i++)ans[i]=cal(n,rk[i]); for (i=1;i<=n;i++)deal(i); for (i=1;i<=tot;i++)solve(i); for (i=1;i<=n;i++) printf ( "%d%c" ,ans[i],i<n? ' ' : '\n' ); for (i=0;i<=tot;i++){ g[i]=id[i]=d[i]=f[i]=0; for (j=0;j<26;j++)son[i][j]=0; } cnt=ed=tot=0; } return 0; } |
D. Secure but True
首先计算出答案串的长度,然后看成11进制下的高精度加法即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #include <bits/stdc++.h> using namespace std ; const int MAXN = 100005 ; typedef long long LL; char s[]={ 'A' , 'H' , 'I' , 'M' , 'O' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' }; int id[333]; char ss[1020]; int a[1020],b[1020]; int c[1020]; LL sum[1020],pww[1020]; const LL Inf=1LL<<50; void upd(LL &pw){ pw*=11; if (pw>=Inf)pw=Inf; } void solve () { int x; scanf ( "%d" ,&x); scanf ( "%s" ,ss); int cnt2= strlen (ss); for ( int i=0;ss[i];i++)b[i]=id[ss[i]]; LL pw=1,cursum=0,sel=-1; sum[cnt2]=0; for ( int i=cnt2-1;i>=0;i--,upd(pw)){ LL cost=(10-b[i])*pw; cursum+=cost; sum[i]=cursum; pww[i]=pw; if (cursum>=x){ sel=i; break ; } } //printf("sel=%lld\n",sel); if (sel>=0){ x-=sum[sel+1]+1; b[sel]+=x/pww[sel]+1; x%=pww[sel]; for ( int i=sel+1;i<cnt2;i++)b[i]=0; int curloc=cnt2-1; while (x){b[curloc--]=x%11;x/=11;} for ( int i=0;i<cnt2;i++) printf ( "%c" ,s[b[i]]); puts ( "" ); return ; } x-=cursum; //printf("x=%d\n",x); pw=pww[0]; upd(pw);upd(pw); //printf("pw=%lld\n",pw); int len=cnt2; if (x>1){ while (x>pw)x-=pw,pw*=11,len++; } len++; //printf("x=%d\n",x); for ( int i=0;i<len;i++){ c[i]=0; } x--; int cnt3=0; while (x){c[cnt3++]=x%11;x/=11;} reverse(c,c+len); for ( int i=0;i<len;i++) printf ( "%c" ,s[c[i]]); puts ( "" ); } int main () { for ( int i=0;i<11;i++)id[s[i]]=i; int T ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { solve () ; } return 0 ; } |
E. Going in Circles
切割点只可能是2个,3个或者4个。
首先特判掉整个环全部都是小写字母的情况,然后将每段小写字符压缩成一块,并计算出在每块内部切割的方案数。
枚举每种大写字符,可以得到要切割的两部分应该分布在哪些范围内,设f[i][j]为第i个字符下某个切割块所属的连通块编号,对f进行Hash,那么一定是在Hash值相同的里面选取两个块,每块切1~2刀。
时间复杂度O(n(26+\log n))。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=50010; const int BASE=10007; typedef long long ll; typedef unsigned long long ull; char a[N]; int block; int T,n,m,i,j,k,f[N],q[N]; int id[N],size[N],vis[N]; ll C2[N],C3[N],C4[N],ans; ull h[N]; inline bool cmp( int x, int y){ return h[x]<h[y];} inline bool small( char x){ return x>= 'a' &&x<= 'z' ;} int F( int x){ return f[x]==x?x:f[x]=F(f[x]);} inline void merge( int x, int y){ if (F(x)!=F(y))f[f[x]]=f[y]; } inline bool special(){ for ( int i=0;i<n;i++) if (!small(a[i])) return 0; return 1; } inline ll solvespecial(){ return C2[n]+C2[3]*C3[n]+2LL*C4[n]; } inline void update( int l, int r, int p){ for ( int i=l;i<=r;i++){ int x=id[f[i]]; if (vis[x]) continue ; vis[x]=1; h[x]+=p; } } inline ll solveoneblock( int n){ return C2[n]+2LL*C3[n]+C4[n]; } int main(){ for (i=1;i<N;i++){ C2[i]=1LL*i*(i-1)/2; C3[i]=1LL*i*(i-1)*(i-2)/6; C4[i]=1LL*i*(i-1)*(i-2)*(i-3)/24; } scanf ( "%d" ,&T); while (T--){ scanf ( "%s" ,a); n= strlen (a); if (special()){ printf ( "%lld\n" ,2LL*solvespecial()); continue ; } for (i=0;i<n;i++)f[i]=i; for (i=0;i<n;i++){ //the divide between i and (i+1)%n if (small(a[i]))merge((i-1+n)%n,i); } for (i=0;i<n;i++)id[i]=0; for (i=1;i<=n;i++)size[i]=0; block=0; for (i=0;i<n;i++){ if (!id[F(i)]){ id[f[i]]=++block; } size[id[f[i]]]++; } ans=0; for (i=1;i<=block;i++)h[i]=0; for ( char O= 'A' ;O<= 'Z' ;O++){ for (i=1;i<=block;i++)h[i]*=BASE,vis[i]=0; m=0; for (i=0;i<n;i++) if (a[i]==O)q[m++]=i; for (i=1;i<m;i++){ update(q[i-1],q[i]-1,i); } } //printf("block=%d\n",block); //for(i=0;i<n;i++)printf("%d ",f[i]);puts(""); for (i=1;i<=block;i++){ ans+=solveoneblock(size[i]); // printf("%d %d %lld\n",i,size[i],solveoneblock(size[i])); } //ans=0; for (i=1;i<=block;i++)q[i]=i; sort(q+1,q+block+1,cmp); for (i=1;i<=block;i=j){ ll sum=0; for (j=i;j<=block&&h[q[i]]==h[q[j]];j++); for (k=i;k<j;k++){ ll ret=C2[size[q[k]]]+size[q[k]]; //printf("%d %d %lld\n",q[k],size[q[k]],ret); //printf("%llu %d %d %lld %lld\n",h[q[k]],q[k],size[q[k]],ret,sum); ans+=ret*sum; sum+=ret; } //[i,j) } printf ( "%lld\n" ,2LL*ans); } return 0; } |
F. Hey JUDgE
暴力枚举所有合并情况然后检验即可。
时间复杂度O(n^5)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #include<cstdio> #include<iostream> #include<string> using namespace std; string s; int T; inline bool check(string s){ static bool v[11]; for ( int i=0;i<11;i++)v[i]=0; for ( int i=0;i<7;i++)v[s[i]]=1; for ( int i=1;i<=5;i++) if (!v[i]) return 0; return 1; } bool solve(){ int i,j,a,b; cin>>s; for (i=0;i<7;i++)s[i]=s[i]- 'A' +1; if (check(s)) return 1; for (i=0;i<7;i++) for (j=0;j<i;j++){ string t=s; t[i]+=t[j]; t[j]=0; if (check(t)) return 1; } for (i=0;i<7;i++) for (j=0;j<i;j++) for (a=0;a<7;a++) for (b=0;b<a;b++){ if (i==a) continue ; if (i==b) continue ; if (j==a) continue ; if (j==b) continue ; string t=s; t[i]+=t[j]; t[j]=0; t[a]+=t[b]; t[b]=0; if (check(t)) return 1; } return 0; } int main(){ cin>>T; while (T--){ puts (solve()? "YES" : "NO" ); } } |
G. Paradise City
按题意模拟即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <bits/stdc++.h> using namespace std ; const int MAXN = 303 ; char s[MAXN][MAXN] ; void solve () { int n ; scanf ( "%d" , &n ) ; for ( int i = 1 ; i <= 3 ; ++ i ) { scanf ( "%s" , s[i] + 1 ) ; } int ans = 0 ; for ( int i = 1 ; i <= 3 ; ++ i ) { for ( int j = 1 ; j <= 3 * n ; ++ j ) if ( s[i][j] == 'X' ) { int t = 0 ; for ( int x = -1 ; x <= 1 ; ++ x ) { for ( int y = -1 ; y <= 1 ; ++ y ) if ( x || y ) { int nx = i + x ; int ny = j + y ; if ( nx < 1 || nx > 3 || ny < 1 || ny > 3 * n ) continue ; if ( s[nx][ny] == '*' ) t += 4 ; } } ans = max ( ans , t ) ; } } printf ( "%d\n" , ans ) ; } int main () { int T ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { solve () ; } return 0 ; } |
H. Another Square in the Floor
ans=\max^2(X,Y)。
1 2 3 4 5 6 7 8 9 10 | #include<bits/stdc++.h> using namespace std; int main(){ int _; scanf ( "%d" ,&_); while (_--){ int n,m; scanf ( "%d%d" ,&n,&m); printf ( "%d\n" ,max(n,m)*max(n,m)); } } |
I. Home Sweet Home
枚举前导零的个数,然后从两边同时开始数位DP即可,一边从高位到低位转移,另一边从低位到高位转移。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | #include <bits/stdc++.h> using namespace std ; const int MAXN = 100005 ; typedef long long LL; int a[44],b[44]; LL dp1[66][2][2]; LL dp2[50][50][2][2][3][3]; int get( int x, int y){ if (x==y) return 0; if (x<y) return 1; return 2; } int check( int can1, int can2, int ncan1, int ncan2){ if (!can1&&ncan1==2) return 0; if (!can2&&ncan2==2) return 0; return 1; } LL dfs2( int cur, int totlen, int can1, int can2, int lcan1, int lcan2){ if (!totlen) return check(can1,can2,lcan1,lcan2); if (totlen%2==0&&cur>=totlen/2) return check(can1,can2,lcan1,lcan2); LL &ret=dp2[cur][totlen][can1][can2][lcan1][lcan2]; if (ret>=0) return ret; ret=0; int x1=a[totlen-cur],x2=b[totlen-cur]; int lx1=a[cur+1],lx2=b[cur+1]; if ((totlen%2==1)&&(cur==totlen/2)){ for ( int t1=0;t1<2;t1++) for ( int t2=0;t2<2;t2++){ if (t1>x1&&!can1) continue ; if (t2>x2&&!can2) continue ; int ncan1=can1||(t1<x1); int ncan2=can2||(t2<x2); ret+=check(ncan1,ncan2,lcan1,lcan2); } return ret; } for ( int t1=0;t1<2;t1++) for ( int t2=0;t2<2;t2++){ if (t1>x1&&!can1) continue ; if (t2>x2&&!can2) continue ; int ncan1=can1||(t1<x1); int ncan2=can2||(t2<x2); for ( int lt1=0;lt1<2;lt1++) for ( int lt2=0;lt2<2;lt2++){ if ((lt1^lt2)!=(t1^t2)) continue ; int nlcan1=get(lt1,lx1); if (!nlcan1)nlcan1=lcan1; int nlcan2=get(lt2,lx2); if (!nlcan2)nlcan2=lcan2; ret+=dfs2(cur+1,totlen,ncan1,ncan2,nlcan1,nlcan2); } } return ret; } LL dfs1( int cur, int can1, int can2){ if (cur<0) return 1; LL &ret=dp1[cur][can1][can2]; if (ret>=0) return ret; ret=0; for ( int t1=0;t1<2;t1++) for ( int t2=0;t2<2;t2++){ if (t1>a[cur]&&!can1) continue ; if (t2>b[cur]&&!can2) continue ; int ncan1=can1||(t1<a[cur]); int ncan2=can2||(t2<b[cur]); if (!(t1^t2)){ ret+=dfs1(cur-1,ncan1,ncan2); } else { if (!cur){ret++; continue ;} for ( int lt1=0;lt1<2;lt1++) for ( int lt2=0;lt2<2;lt2++){ if ((lt1^lt2)!=1) continue ; int nlt1=get(lt1,a[0]); int nlt2=get(lt2,b[0]); ret+=dfs2(0,cur-1,ncan1,ncan2,nlt1,nlt2); } } } return ret; } LL solve(LL x,LL y){ for ( int i=0;i<43;i++){a[i]=x&1;x>>=1;} for ( int i=0;i<43;i++){b[i]=y&1;y>>=1;} memset (dp1,-1, sizeof dp1); memset (dp2,-1, sizeof dp2); LL ret=dfs1(42,0,0); return ret; } void go () { LL L,R; scanf ( "%lld%lld" ,&L,&R); //printf("ans1=%lld\n",solve(0,4)); //printf("ans2=%lld\n",solve(4,0)); //return ; LL ans=solve(R,R); //printf("ans=%lld\n",ans); if (L)ans-=solve(L-1,R); //printf("ans=%lld\n",ans); if (L)ans-=solve(R,L-1); //printf("ans=%lld\n",ans); if (L)ans+=solve(L-1,L-1); printf ( "%lld\n" ,ans); } int main () { int T ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { go () ; } return 0 ; } |
J. Smooth Developer
按题意模拟即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <bits/stdc++.h> using namespace std ; const int MAXN = 100005 ; map < string , int > mp1 ; map < int , string > mp2 ; int n , m , cnt ; vector < int > G[MAXN] ; int vis[MAXN] ; char s[20] ; int get () { scanf ( "%s" , s ) ; if ( mp1.count ( s ) ) return mp1[s] ; ++ cnt ; mp1[s] = cnt ; mp2[cnt] = s ; return cnt ; } void dfs ( int u ) { if ( vis[u] ) return ; vis[u] = 1 ; for ( int i = 0 ; i < G[u].size () ; ++ i ) { int v = G[u][i] ; dfs ( v ) ; } } void solve () { cnt = 0 ; mp1.clear () ; mp2.clear () ; scanf ( "%d%d" , &n , &m ) ; for ( int i = 1 ; i <= n ; ++ i ) { G[i].clear () ; vis[i] = 0 ; } for ( int i = 1 ; i <= n ; ++ i ) { int u = get () , c ; scanf ( "%d" , &c ) ; for ( int j = 0 ; j < c ; ++ j ) { int v = get () ; G[u].push_back ( v ) ; } } for ( int i = 1 ; i <= m ; ++ i ) { int u = get () ; dfs ( u ) ; } for ( int i = 1 ; i <= n ; ++ i ) { if ( vis[i] ) cout << mp2[i] << endl ; } } int main () { int T ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { solve () ; } return 0 ; } |
K. Betrayed
首先对于每棵树两遍DP求出以每个点为根的最大深度,就可以得到每棵树爆栈的概率,递推求出期望步数即可。
时间复杂度O(Cn)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | #include <bits/stdc++.h> using namespace std ; const int MAXN = 100005 ; typedef long long LL; vector < int > G[MAXN] ; int dp[MAXN] , dp2[MAXN] ; double p[22] ; double f[22] ; //double a[22][22] ; int C , K , n ; void dfs2 ( int u , int f ) { int maxv = 0 ; for ( int i = 0 ; i < G[u].size () ; ++ i ) { int v = G[u][i] ; if ( v == f ) continue ; dp2[v] = max ( dp2[u] + 1 , maxv ) ; maxv = max ( maxv , dp[v] + 2 ) ; } maxv = 0 ; for ( int i = G[u].size () - 1 ; ~i ; -- i ) { int v = G[u][i] ; if ( v == f ) continue ; dp2[v] = max ( dp2[v] , maxv ) ; maxv = max ( maxv , dp[v] + 2 ) ; } for ( int i = 0 ; i < G[u].size () ; ++ i ) { int v = G[u][i] ; if ( v == f ) continue ; dfs2 ( v , u ) ; } } void dfs ( int u , int f ) { for ( int i = 0 ; i < G[u].size () ; ++ i ) { int v = G[u][i] ; if ( v == f ) continue ; dfs ( v , u ) ; dp[u] = max ( dp[u] , dp[v] + 1 ) ; } } /* void gauss ( int n , int m ) { int r = 0 , c = 0 ; for ( ; r < n && c < m ; ++ c ) { int tr = r ; for ( int i = r ; i < n ; ++ i ) { if ( a[i][c] > a[tr][c] ) tr = i ; } if ( fabs ( a[tr][c] ) < 1e-8 ) continue ; for ( int i = c ; i <= C ; ++ i ) { swap ( a[r][i] , a[tr][i] ) ; } for ( int i = C ; i >= c ; -- i ) a[r][i] /= a[r][c] ; for ( int i = 0 ; i < n ; ++ i ) if ( i != r && fabs ( a[i][c] ) > 1e-8 ) { for ( int j = C ; j >= c ; -- j ) { a[i][j] -= a[r][j] * a[i][c] ; } } ++ r ; } for ( int i = r - 1 ; i ; -- i ) { for ( int j = } } */ void solve () { scanf ( "%d%d" , &C , &K ) ; for ( int i = 1 ; i <= C ; ++ i ) { scanf ( "%d" , &n ) ; for ( int j = 1 ; j <= n ; ++ j ) { G[j].clear () ; dp[j] = dp2[j] = 0 ; } for ( int j = 2 , x ; j <= n ; ++ j ) { scanf ( "%d" , &x ) ; G[j].push_back ( x ) ; G[x].push_back ( j ) ; } dfs ( 1 , 1 ) ; dfs2 ( 1 , 1 ) ; int cnt = 0 ; for ( int j = 1 ; j <= n ; ++ j ) { if ( max ( dp2[j] , dp[j] ) <= K ) ++ cnt ; } p[i] = 1.0 * cnt / n ; //a[i][i] = 1 ; //a[i][i + 1] = -p[i] ; //a[i][0] = ( 1 - p[i] ) ; //a[i][C] = 4 - 3 * p[i] ; } double pp = 1 ; f[1] = -3 ; for ( int i = C ; i >= 1 ; -- i ) { pp *= p[i] ; if ( i > 1 ) f[1] += 1.0 / pp ; else f[1] += 4.0 / pp ; } printf ( "%.4f\n" , f[1] ) ; //a[C][C] = 1 ; //gauss ( C + 1 , C + 1 ) ; } int main () { int T ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { solve () ; } return 0 ; } |
L. Chance
预处理出f[i]表示[1,i]中二进制下1的个数为素数的个数,然后O(1)回答即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include<bits/stdc++.h> using namespace std; const int N=100010; int f[N],vis[N]; int main(){ vis[1]=1; for ( int i=2;i<N;i++) if (!vis[i]) for ( int j=i+i;j<N;j+=i)vis[j]=1; int _; scanf ( "%d" ,&_); for ( int i=1;i<=100000;i++){ f[i]=f[i-1]; if (!vis[__builtin_popcount(i)])f[i]++; } while (_--){ int l,r; scanf ( "%d%d" ,&l,&r); if (!l)l=1; printf ( "%d\n" ,f[r]-f[l-1]); } } |
M. ACPC Headquarters : AASTMT (Stairway to Heaven)
设f[i][j]表示志愿者i在第j天需要服务几个赛事,然后检查是否存在j满足f[i][j]>1即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #include<iostream> #include<string> #include<map> using namespace std; int Case,n; string s; map<string, int >T; int m,f[10010][370]; inline int getid(){ cin>>s; int &t=T[s]; if (t) return t; return t=++m; } inline void make( int x, int l, int r){ for ( int i=l;i<=r;i++)f[x][i]++; } inline bool check( int x){ for ( int i=1;i<=365;i++) if (f[x][i]>1) return 1; return 0; } int main(){ cin>>Case; while (Case--){ cin>>n; T.clear(); int ans=0; while (n--){ cin>>s; int l,r,k; cin>>l>>r>>k; while (k--){ int x=getid(); make(x,l,r); } } for (map<string, int >::iterator it=T.begin();it!=T.end();it++){ if (check(it->second))ans++; } cout<<ans<<endl; for (map<string, int >::iterator it=T.begin();it!=T.end();it++){ if (check(it->second))cout<<it->first<<endl; } for ( int i=1;i<=m;i++) for ( int j=1;j<=365;j++)f[i][j]=0; m=0; } return 0; } |
总结:
- D题_ilovelife对Claris提供的做法理解上出现了偏差,导致写了一个小时,还交了3发才通过。间接导致I题没有写完,以致没有AK。发生这种情况应考虑换人写。
- E题poursoul在Claris写代码时进行误导,致使原来正确的公式被改成错误的公式,无故增加一发罚时,下次要注意。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步