国庆第三次集训: 2012 ACM-ICPC Asia Regional Contest Chengdu Site
A: Extremely easy. It requires you to add all the ASCII value of a string together.
AC Code:
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<math.h> 4 #include<string.h> 5 #include<queue> 6 #include<algorithm> 7 #include<cstdio> 8 #define ll long long 9 #define lson l,m,rt<<1; 10 #define rson m+1,r,rt<<1|1; 11 using namespace std; 12 13 int main(){ 14 int T; 15 int kase=0; 16 while(~scanf("%d",&T)){ 17 scanf("%d",&T); 18 int MAX=0; 19 char s[1000]; 20 for(int i=1;i<=T;i++){ 21 scanf("%s",s); 22 int len=strlen(s); 23 int tmp=0; 24 for(int i=0;i<len;i++){ 25 tmp+=s[i]; 26 } 27 MAX=max(tmp,MAX); 28 } 29 printf("Case %d: %d\n",++kase, MAX); 30 } 31 }
B: A probability problem. It is actually very easy, I have even listed the correct formula in the contest, however, it seems that p^n is sometimes too small and I started to doubt my intuitive and turned to solve it by dynamic programming. It did not work out. The official solution frustrated me because I was right! The only difference between WA code and AC code is subtle.
WA code:
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<math.h> 4 #include<string.h> 5 #include<queue> 6 #include<algorithm> 7 #include<cstdio> 8 #define ll long long 9 #define lson l,m,rt<<1; 10 #define rson m+1,r,rt<<1|1; 11 using namespace std; 12 13 int main(){ 14 int n;double p;int kase=0; 15 while(~scanf("%d%lf",&n,&p)){ 16 long double E1=0; 17 long double E2=0; 18 long double temp1=pow(p,n+1); 19 long double temp2=pow(1-p,n+1); 20 21 long double tmp=1.0*n; 22 for(int i=0;i<n;i++){ 23 E1+=tmp; 24 tmp=tmp*(1-p)*(n+i+1)*(n-i-1)/(i+1)/(n-i); 25 } 26 for(int i=1;i<=n+1;i++){ 27 E1*=p; 28 } 29 tmp=1.0*n;//printf("%Lf %Lf\n",temp1,E1); 30 for(int i=0;i<n;i++){ 31 E2+=tmp; 32 tmp=tmp*p*(n-i-1)/(n-i)*(n+i+1)/(i+1); 33 } 34 for(int i=1;i<=n+1;i++){ 35 E2*=(1-p); 36 } 37 long double E=E1+E2;//printf("%Lf %Lf\n",temp2,E2); 38 printf("Case %d: %Lf\n",++kase,E); 39 } 40 }
AC code:
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<math.h> 4 #include<string.h> 5 #include<queue> 6 #include<algorithm> 7 #include<cstdio> 8 #define ll long long 9 #define lson l,m,rt<<1; 10 #define rson m+1,r,rt<<1|1; 11 using namespace std; 12 13 int main(){ 14 int n;double p;int kase=0; 15 while(~scanf("%d%lf",&n,&p)){ 16 double E1=0; 17 double E2=0; 18 19 double tmp=1.0*n; 20 int cnt1=0; 21 for(int i=0;i<n;i++){ 22 E1+=tmp; 23 tmp=tmp*(1-p)*(n+i+1)*(n-i-1)/(i+1)/(n-i); 24 while(E1>n){ 25 tmp*=p; 26 E1*=p; 27 cnt1++; 28 if(cnt1>=n+1){ 29 break; 30 } 31 } 32 } 33 for(int i=1;i<=n+1-cnt1;i++){ 34 E1*=p; 35 } 36 tmp=1.0*n;//printf("%Lf %Lf\n",temp1,E1); 37 int cnt2=0; 38 for(int i=0;i<n;i++){ 39 E2+=tmp; 40 tmp=tmp*p*(n-i-1)/(n-i)*(n+i+1)/(i+1); 41 while(E2>n){ 42 tmp*=(1-p); 43 E2*=(1-p); 44 cnt2++; 45 if(cnt2>=n+1){ 46 break; 47 } 48 } 49 } 50 for(int i=1;i<=n+1-cnt2;i++){ 51 E2*=(1-p); 52 } 53 double E=E1+E2;//printf("%Lf %Lf\n",temp2,E2); 54 printf("Case %d: %.6lf\n",++kase,E); 55 } 56 }
I: Extremely easy. DP can solve it elegantly.
AC Code:
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<math.h> 4 #include<string.h> 5 #include<queue> 6 #include<algorithm> 7 #include<cstdio> 8 #define ll long long 9 #define lson l,m,rt<<1; 10 #define rson m+1,r,rt<<1|1; 11 using namespace std; 12 13 const ll mod=1e9+7; 14 ll dp[1005]; 15 16 void fun(int n){ 17 dp[n]=(dp[n]+dp[n-1])%mod; 18 for(int i=2;i<=n-1;i++){ 19 int tmp=n-i-1; 20 tmp/=i; 21 if(tmp*i==n-i-1){ 22 dp[n]=(dp[tmp+1]+dp[n])%mod; 23 } 24 } 25 } 26 27 void init(){ 28 for(int i=1;i<=1000;i++){ 29 dp[i]=0; 30 } 31 dp[1]=dp[0]=1; 32 for(int i=2;i<=1000;i++){ 33 fun(i); 34 } 35 } 36 37 int main(){ 38 int n,kase=0; 39 init(); 40 while(~scanf("%d",&n)){ 41 printf("Case %d: %lld\n",++kase,dp[n]); 42 } 43 }
K: A problem of high quality! I firstly thought we can list multiples of N and find if it can satisfy the requirements. Sadly though we cannot know when can we stop searching. The official solution uses a property cleverly: if A=B(mod N), then (A*10+i)=(B*10+i) (mod N), (0<=i<=9). Thus, we need only search those node in N-ring. In other word, if num%N has been visited, we will not search it further.
AC code:
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<math.h> 4 #include<string.h> 5 #include<queue> 6 #include<algorithm> 7 #include<cstdio> 8 #define ll long long 9 #define lson l,m,rt<<1; 10 #define rson m+1,r,rt<<1|1; 11 using namespace std; 12 13 int pre[10000+5],mod[10000+5],num[10000+5]; 14 bool vis[10000+5]; 15 int limit[1000]; 16 int n,m,kase=0; 17 18 void print(int v){ 19 if(v==-1)return ; 20 print(pre[v]); 21 printf("%d",num[v]); 22 return ; 23 } 24 25 bool limited(int t){ 26 for(int i=0;i<m;i++){ 27 if(limit[i]==t)return true; 28 } 29 return false; 30 } 31 32 void bfs(){ 33 for(int i=0;i<n;i++){ 34 pre[i]=-1;vis[i]=false; 35 } 36 queue <int> q; 37 for(int i=1;i<=9;i++){ 38 if(limited(i))continue; 39 int v=i%n; 40 if(!vis[v]){ 41 q.push(v); 42 vis[v]=true; 43 num[v]=i; 44 } 45 } 46 while(!q.empty()){ 47 int u=q.front();q.pop(); 48 if(u==0){ 49 print(u);return ; 50 } 51 for(int i=0;i<=9;i++){ 52 if(limited(i))continue; 53 int MOD=(10*u+i)%n; 54 if(!vis[MOD]){ 55 vis[MOD]=true; 56 q.push(MOD); 57 pre[MOD]=u; 58 num[MOD]=i; 59 } 60 } 61 } 62 printf("-1"); 63 } 64 65 int main() { 66 while(~scanf("%d%d",&n,&m)) { 67 for(int i=0; i<m; i++) { 68 scanf("%d",&limit[i]); 69 } 70 71 72 73 printf("Case %d: ",++kase); 74 bfs(); 75 printf("\n"); 76 } 77 }