2013 Dhaka 区域赛
A.uva 12709 Falling ANTS
首先按照H排序,然后按照L*H*W排序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include <math.h> 4 #include<algorithm> 5 #include<string.h> 6 #define maxn 100009 7 #define inf 100000 8 using namespace std; 9 int main() 10 { 11 int n,a,b,c; 12 while(1) 13 { 14 int ans=0,ans_h=0; 15 scanf("%d",&n); 16 if(n==0)break; 17 for(int i=1;i<=n;i++) 18 { 19 scanf("%d%d%d",&a,&b,&c); 20 if(c>ans_h)ans_h=c,ans=a*b*c; 21 else if(c==ans_h && a*b*c>ans)ans=a*b*c; 22 } 23 printf("%d\n",ans); 24 } 25 return 0; 26 }
D uva 12712 Pattern Locker
题目大意:一个L*L的安卓密码锁,问最少按M个钮,最多按N个扭,一共有多少中不同的方式加锁,注意正常来说1 3 2,是不合法的,但在这里是合法的,但同一个按钮还是不能走两次
思路:排列组合一下就出来了,比如第一个样例:9*8*7*6+9*8*7*6*5+9*8*7*6*5*4+9*8*7*6*5*4*3+9*8*7*6*5*4*3*2+9*8*7*6*5*4*3*2*1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include <math.h> 4 #include<algorithm> 5 #include<string.h> 6 #define maxn 100009 7 #define inf 100000 8 #define MOD (10000000000007ll) 9 using namespace std; 10 int main() 11 { 12 int t,cas=0; 13 scanf("%d",&t); 14 while(t--) 15 { 16 long long a,b,c; 17 scanf("%lld%lld%lld",&a,&b,&c); 18 long long u=a*a,ans=1; 19 for(int i=1;i<=b;i++)ans=ans*(u-i+1)%MOD; 20 long long temp=ans; 21 for(int i=b+1;i<=c;i++) 22 temp=(temp*(u-i+1))%MOD,ans=(ans+temp%MOD)%MOD; 23 printf("Case %d: %lld\n",++cas,ans); 24 } 25 return 0; 26 }
E uva 12713 Pearl Chains
题目大意:有三种类型的珍珠,每种类型的珍珠分别能够染色x,y,z种颜色,1号类型珍珠加3号类型珍珠共A个,2号类型珍珠和3号类型珍珠共B个,问有多少种摆珍珠的方案
思路:公式在比赛的时候就推出来了,枚举2号类型的珍珠个数即可 ΣC(i,A+B-i)*C(A-i,A+B-2*i)*xA-1*yB-1*zi,关键数字太大,还需要lucas定理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include <math.h> 4 #include<algorithm> 5 #include<string.h> 6 #include<queue> 7 #define MOD 1000003 8 #define maxn 1000000 9 using namespace std; 10 long long fac[MOD+10],inv[MOD+10],a,b,x,y,z; 11 long long mpow(long long a,long long n){ 12 if(n==0)return 1; 13 if(n==1)return a%MOD; 14 if(n&1)return (a*mpow(a,n-1))%MOD; 15 else{ 16 long long u=mpow(a,n>>1); 17 return (u*u)%MOD; 18 } 19 } 20 long long C(long long m,long long n) 21 { 22 if(m==0)return 1; 23 return ((fac[n]*inv[m]%MOD)*inv[n-m])%MOD; 24 } 25 int main() 26 { 27 int t; 28 fac[0]=inv[0]=1; 29 for(int i=1;i<=MOD;i++) 30 { 31 fac[i]=(fac[i-1]*(long long)i)%MOD; 32 inv[i]=mpow(fac[i],MOD-2); 33 // cout << fac[i]<<" "<<inv[i]<<endl; 34 } 35 scanf("%d",&t); 36 //printf("%lld\n",C(2,5)); 37 while (t--) 38 { 39 long long ans=1; 40 scanf("%lld%lld%lld%lld%lld",&a,&b,&x,&y,&z); 41 x%=MOD;y%=MOD;z%=MOD; 42 while(a||b) 43 { 44 long long u=a%MOD,v=b%MOD,min_x=min(u,v),ret=0,temp=1; 45 for(int i=0;i<=min_x;i++) 46 { 47 temp=(C(i,u+v-i)*C(u-i,u+v-i-i))%MOD; 48 temp=(temp*mpow(x,u-i))%MOD; 49 temp=(temp*mpow(y,v-i))%MOD; 50 temp=(temp*mpow(z,i))%MOD; 51 ret=(ret+temp)%MOD; 52 } 53 ans=(ans*ret)%MOD; 54 a/=MOD,b/=MOD; 55 } 56 printf("%lld\n",ans); 57 } 58 return 0; 59 }
F uva 12714 Two Points Revisited
题目大意:给你两个点,要你再求两点,使得与题目中给出的两点垂直,并且两点要在矩形框内,输出任意一种即可
思路:思路很多,CP和zyx分别有自己的思路,其实就是个sb题,我的话先求出任意一条垂直的两点,然后将其平移到第一象限,然后再将其移到第一象限的左下角即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include <math.h> 4 #include<algorithm> 5 #include<string.h> 6 #define maxn 100009 7 #define inf 100000 8 #define MOD (10000000000007ll) 9 using namespace std; 10 int main() 11 { 12 int t,cas=0,x1,y1,x2,y2,x3,x4,y3,y4; 13 scanf("%d",&t); 14 while(t--) 15 { 16 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 17 x3=x1,y3=y1,x4=x1+y2-y1,y4=y1-(x2-x1); 18 if(x3<0)x4-=x3,x3=0; 19 if(y3<0)y4-=y3,y3=0; 20 if(x4<0)x3-=x4,x4=0; 21 if(y4<0)y3-=y4,y4=0; 22 int u=min(y4,y3); 23 y4-=u,y3-=u; 24 u=min(x4,x3); 25 x4-=u;x3-=u; 26 printf("Case %d: %d %d %d %d\n",++cas,x3,y3,x4,y4); 27 } 28 return 0; 29 }
H UVA 12716 GCD XOR
题目大意:有多少小于等于N的数对(A,B),满足GCD(A,B)=A XOR B 1<=B<=A<=N
思路:感觉能想出这题真心好不容易!!!关键要知道一个结论:设GCD(A,B)= C ,A-C=B
以上结论在打过N张表后被总结下来,其中ZYX在这道题几乎耗了3个多小时TUT,知道结论以后暴力即可!
然后照着结论推证明
A-B<=A XOR B<=A+B (由于XOR可以理解成不带进位的加法,同样也可以理解成不带借位的减法)
∵A XOR B=GCD(A,B)
∴A-B<=GCD(A,B)<=A+B
同时由辗转相减法可得GCD(A,B)=GCD(A-B,B)<=A-B
即A-B<=GCD(A,B)<=A-B
QED.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include <math.h> 4 #include<algorithm> 5 #include<string.h> 6 #include<queue> 7 #define maxn 30000000 8 #define inf 100000 9 #define MOD (10000000000007ll) 10 using namespace std; 11 int ans[maxn]; 12 int main() 13 { 14 for(int i=1;i<=maxn;i++) 15 for(int j=2;j*i<=maxn;j++) 16 { 17 int u=i*j,b=u-i; 18 if((b^u)==i)ans[u]++; 19 } 20 for(int i=2;i<=maxn;i++)ans[i]+=ans[i-1]; 21 int t,n,cas=0; 22 scanf("%d",&t); 23 while(t--) 24 { 25 scanf("%d",&n); 26 printf("Case %d: %d\n",++cas,ans[n]); 27 } 28 return 0; 29 }
I UVA 12717 Fiasco
题目大意:前面给了一坨眼睛都快看出血的代码,其实是prim,所以它做的应该是求出以s为根的最小生成树,而要最小生成树上的边正好等于最短路树
思路:这题的话DFS序和BFS序应该都行,一开始看样例构造了个BFS序就过了,证明的话以DFS序为例子,假设现在正在遍历非树边,那它的序号一定比所有的树边大,并且当前构成环,由MST回路性质可得该边肯定不是MST上的边,很明显该边也肯定不是最短路树上的边
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include <math.h> 4 #include<algorithm> 5 #include<string.h> 6 #include<queue> 7 #define maxn 250000 8 #define inf 100000 9 #define MOD (10000000000007ll) 10 using namespace std; 11 int cnt=0; 12 int head[maxn],next[maxn],point[maxn],now=1; 13 int ans[maxn],n,m,source,x[maxn],y[maxn],v[maxn]; 14 bool visit[maxn],visit1[maxn]; 15 void add(int x,int y,int v) 16 { 17 next[++now]=head[x]; 18 head[x]=now; 19 point[now]=y; 20 } 21 void bfs(int s) 22 { 23 queue<int>q; 24 q.push(s); 25 visit[s]=1; 26 while(!q.empty()) 27 { 28 s=q.front(); 29 q.pop(); 30 for(int i=head[s];i;i=next[i])if(!visit1[i]) 31 { 32 visit1[i]=visit1[i^1]=1; 33 int u=point[i]; 34 ans[i>>1]=++cnt; 35 if(!visit[u])q.push(u),visit[u]=1; 36 } 37 } 38 } 39 int main() 40 { 41 int t,cas=0; 42 scanf("%d",&t); 43 while(t--) 44 { 45 now=1; cnt=0; 46 memset(visit,0,sizeof(visit)); 47 memset(visit1,0,sizeof(visit1)); 48 memset(head,0,sizeof(head)); 49 scanf("%d%d%d",&n,&m,&source); 50 printf("Case %d:\n",++cas); 51 for(int i=1;i<=m;i++) 52 { 53 scanf("%d%d%d",&x[i],&y[i],&v[i]); 54 add(x[i],y[i],v[i]); 55 add(y[i],x[i],v[i]); 56 } 57 bfs(source); 58 //printf("%d\n",cnt); 59 for(int i=1;i<=m;i++) 60 { 61 printf("%d %d %d\n",x[i],y[i],ans[i]); 62 } 63 } 64 return 0; 65 }
J uva 12718 Dromicpalin Substrings
题目大意:一个字符串,有多少连续的子串可以重排成回文串
思路:显然能够重排成回文串的字符串奇数个字符的个数小于等于1,然后O(n^2)扫一遍就行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include <math.h> 4 #include<algorithm> 5 #include<string.h> 6 #define maxn 100009 7 #define inf 100000 8 #define MOD (10000000000007ll) 9 using namespace std; 10 char ch[maxn]; 11 int visit[30]; 12 int main() 13 { 14 int t,cas=0; 15 scanf("%d",&t); 16 while(t--) 17 { 18 int ans=0,odd; 19 scanf("%s",ch+1); 20 int len=strlen(ch+1); 21 for(int i=1;i<=len;i++) 22 { 23 memset(visit,0,sizeof(visit)); 24 for(int j=i;j>=1;j--) 25 { 26 if(i==j) 27 { 28 visit[ch[i]-'a']=1; 29 odd=1; 30 ans++; 31 } 32 else 33 { 34 visit[ch[j]-'a']=visit[ch[j]-'a']+1; 35 if(visit[ch[j]-'a']&1)odd++; 36 else odd--; 37 if(odd<=1)ans++; 38 } 39 } 40 } 41 printf("Case %d: %d\n",++cas,ans); 42 } 43 return 0; 44 }