A.http://codeforces.com/contest/552/problem/A
题意:有一个100*100的桌面(x从左到右增大,y从下到上增大),刚开始每个位置的数字都是0。现给出n个矩形,对于每个矩形每次给出x1,y1,x2,y2,表示矩形左下角和右下角的坐标,每个矩形位置中的数字都+1,求整个桌面上的数字之和
分析:暴力即可,将每次所给矩形的面积相加即是最后的答案。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=105; 6 int mp[maxn][maxn]; 7 8 int main() 9 { 10 int n,m,i,j,k,x,y,z,x1,x2,y1,y2; 11 long long ans; 12 while ( scanf("%d",&m)!=EOF ) { 13 ans=0; 14 while ( m-- ) { 15 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 16 ans+=(x2-x1+1)*(y2-y1+1); 17 } 18 printf("%lld\n",ans); 19 } 20 return 0; 21 }
B.http://codeforces.com/contest/552/problem/B
题意:每次给一个n,计算从1到n所有数字的位数之和
分析:模拟题,暴力即可。以y=pow(10,i-1)-1到x=pow(10,i)-1 (1<=i<=9)为一部分,每次将该部分的范围(即x-y)*i即是该部分所有数的位数之和,最后累加即可
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 7 int main() 8 { 9 int n,m,i,j,k,x,y,z,s; 10 long long ans; 11 while ( scanf("%d",&n)!=EOF ) { 12 ans=0; 13 for ( i=1;i<=9;i++ ) { 14 x=pow(10,i)-1; 15 y=pow(10,i-1)-1; 16 if ( n<=x ) { 17 ans+=(long long)(n-y)*i; 18 break; 19 } 20 else ans+=(long long)(x-y)*i; 21 } 22 if ( n==1000000000 ) ans+=10; 23 printf("%lld\n",ans); 24 } 25 return 0; 26 }
C.http://codeforces.com/contest/552/problem/C
题意:现有重量为m的物体放天平的一侧,w^0,w^1……w^100的砝码各一个,砝码可以放天平的任意一侧,先求天平是否可以平衡
分析:法1:采用w进制的思想,把重量为m的物体从10进制化为w进制,然后从低位到高位遍历。当在m的w进制下的某一位上的数字是0/1时则一定是可行的(0不进行任何操作,1在另一边放一个相对应的砝码)。若某一位为w-1||w也是可行的(因为都可以进一位,即在放物体的那边添加一个相对应的砝码使其进位),再通过在另一边放一个对应的高位质量的砝码进行抵消。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=105; 6 int a[maxn]; 7 8 int main() 9 { 10 int w,m,i,j,k,x,y,z,cnt; 11 bool flag; 12 while ( scanf("%d%d",&w,&m)!=EOF ) { 13 cnt=0; 14 memset(a,0,sizeof(a)); 15 while ( m ) { 16 a[cnt++]=m%w; 17 m/=w; 18 } 19 flag=true; 20 for ( i=0;i<=cnt;i++ ) { 21 if ( a[i]!=0 && a[i]!=1 && a[i]!=w-1 && a[i]!=w ) { 22 flag=false; 23 break; 24 } 25 if ( a[i]==w-1 || a[i]==w ) { 26 a[i+1]++; 27 } 28 } 29 if ( flag ) printf("YES\n"); 30 else printf("NO\n"); 31 } 32 return 0; 33 }
法2:采用数学的做法,w0*c0+w1*c1+……+w100*c100=m(wn表示w的n次方,而c0可以为0,-1,1。 0代表不加该砝码,1代表在在放物体的另一边加砝码,-1代表在放物体的那边加砝码)将该式记作一式。
将一式进行变形得到二式:c1+w2*(c2-1)+w3(c3-1)+……+w100(c100-1)=(m-c0)/w,所以当m-c0能够整除w时才有解,此时二式又变回了一式,所以我们可以不断递归下去直至满足要求
而存在几种特殊情况,即w<=3||m==1时是一定有答案的。
两个核心函数
bool solve(int w,int m)
{
if ( w<=3 || m==1 || trysolve(w,m-1) || trysolve(w,m+1) || trysolve(w,m) ) return true;
return false;
}
bool trysolve(int w,int m)
{
return ( m%w==0 && solve(w,m/w) );
}
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 bool solve(int w,int m); 6 bool trysolve(int w,int m); 7 8 bool solve(int w,int m) 9 { 10 if ( w<=3 || m==1 || trysolve(w,m-1) || trysolve(w,m+1) || trysolve(w,m) ) return true; 11 return false; 12 } 13 14 bool trysolve(int w,int m) 15 { 16 return ( m%w==0 && solve(w,m/w) ); 17 } 18 19 int main() 20 { 21 int w,m,i,j,k,x,y,z; 22 bool flag; 23 while ( scanf("%d%d",&w,&m)!=EOF ) { 24 flag=solve(w,m); 25 if ( flag ) printf("YES\n"); 26 else printf("NO\n"); 27 } 28 return 0; 29 }
D.http://codeforces.com/contest/552/problem/D
题意:有n个点,求能组成多少个三角形
分析:法1:暴力求解,每次枚举三个点判断是否共线,若不共线,则ans++
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 typedef long long ll; 7 const int maxn=2005; 8 struct edge{ 9 int x,y; 10 }arr[maxn]; 11 12 bool judge(int x1,int y1,int x2,int y2) 13 { 14 return (y1*x2-x1*y2); 15 } 16 17 int main() 18 { 19 int n,m,i,j,k,x,y,z,x1,y1,x2,y2; 20 ll ans; 21 while ( scanf("%d",&n)!=EOF ) { 22 for ( i=1;i<=n;i++ ) scanf("%d%d",&arr[i].x,&arr[i].y); 23 ans=0; 24 for ( i=1;i<=n;i++ ) { 25 for ( j=i+1;j<=n;j++ ) { 26 for ( k=j+1;k<=n;k++ ) { 27 x1=arr[i].x-arr[j].x; 28 y1=arr[i].y-arr[j].y; 29 x2=arr[i].x-arr[k].x; 30 y2=arr[i].y-arr[k].y; 31 if ( judge(x1,y1,x2,y2) ) ans++; 32 } 33 } 34 } 35 printf("%lld\n",ans); 36 } 37 return 0; 38 }
法2:按输入顺序从小到大(1-n)固定点,在将这个点(i)和其他点的斜率都算出来,用map保存斜率和出现的次数。若没有任何一条斜率相同,则ans+=C(n-i,2),即在n-i个点中选两个点。遍历每个斜率然后对每个斜率k出现的次数mp[k]进行ans-=C(x,2) ,即这x个点中任意两个点都不能和i构成三角形。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<map> 6 using namespace std; 7 typedef long long ll; 8 const int maxn=2010; 9 struct edge{ 10 int x,y; 11 }arr[maxn]; 12 13 int main() 14 { 15 int n,m,i,j; 16 double k; 17 ll sum,ans,x,y,z; 18 while ( scanf("%d",&n)!=EOF ) { 19 sum=0; 20 for ( i=1;i<=n;i++ ) scanf("%d%d",&arr[i].x,&arr[i].y); 21 for ( i=1;i<=n;i++ ) { 22 map<double,int>mp; 23 map<double,int>::iterator it; 24 ans=(n-i)*(n-i-1)/2; 25 int num=0; 26 for ( j=i+1;j<=n;j++ ) { 27 if ( arr[i].x!=arr[j].x ) { 28 k=(double)(double)(arr[i].y-arr[j].y)/(double)(arr[i].x-arr[j].x); 29 if ( !mp[k] ) mp[k]=1; 30 else mp[k]++; 31 } 32 else num++; 33 } 34 for ( it=mp.begin();it!=mp.end();it++ ) { 35 x=it->second; 36 ans-=(x-1)*x/2; 37 } 38 ans-=(num-1)*num/2; 39 sum+=ans; 40 } 41 printf("%lld\n",sum); 42 } 43 return 0; 44 }
E.http://codeforces.com/contest/552/problem/E
题意:给定一个只含+和*运算符的数学表达式,先要求添加一对括号使得最后的值最大
分析:大模拟。记录每个乘号的位置,最后的括号一定是添加到某两个称号之间的。为了简化计算,在头和尾都*1。对于计算某个表达式设置x,y,初始时x=0,y=firstnum,若下一个操作符为“+”则x+=y,y=nextnum;若下一个操作符为“*”,则x不变,y*=nextnum。最后暴力在任意两个乘号之间添加括号,计算结果
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<map> 6 #include<set> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 const ll maxn=5010; 11 const ll maxm=3010; 12 char s[maxn]; 13 ll a[maxm],cnta,cntp; 14 char p[maxm]; 15 vector<ll>mul; 16 17 ll cal(ll l,ll r,ll add) 18 { 19 ll x,y,i; 20 x=0; 21 y=a[1]; 22 for ( i=1;i<=cntp;i++ ) { 23 if ( i==l ) { 24 y*=add; 25 i=r-1; 26 continue; 27 } 28 if ( p[i]=='+' ) { 29 x+=y; 30 y=a[i+1]; 31 } 32 else y*=a[i+1]; 33 } 34 x+=y; 35 return x; 36 } 37 38 ll add_(ll l,ll r) 39 { 40 ll x,y,i; 41 x=0; 42 y=a[l]; 43 for ( i=l;i<=r-1;i++ ) { 44 if ( p[i]=='+' ) { 45 x+=y; 46 y=a[i+1]; 47 } 48 else y*=a[i+1]; 49 } 50 x+=y; 51 return x; 52 } 53 54 int main() 55 { 56 ll n,m,i,j,k,len,num,x,y,ans,now,add,l,r; 57 while ( scanf("%s",s)!=EOF ) { 58 len=strlen(s); 59 mul.clear(); 60 cnta=cntp=1; 61 a[cnta]=1; 62 p[cntp]='*'; 63 mul.push_back(cntp); 64 for ( i=0;i<len;i++ ) { 65 if ( i%2==0 ) { 66 a[++cnta]=s[i]-'0'; 67 } 68 else { 69 p[++cntp]=s[i]; 70 if ( s[i]=='*' ) mul.push_back(cntp); 71 } 72 } 73 a[++cnta]=1; 74 p[++cntp]='*'; 75 mul.push_back(cntp); 76 x=0; 77 y=a[1]; 78 for ( i=1;i<=cntp;i++ ) { 79 if ( p[i]=='+' ) { 80 x+=y; 81 y=a[i+1]; 82 } 83 else y*=a[i+1]; 84 } 85 x+=y; 86 ans=x; 87 for ( i=0;i<mul.size()-1;i++ ) { 88 l=mul[i]; 89 for ( j=i+1;j<mul.size();j++ ) { 90 r=mul[j]; 91 if ( l+1==r ) continue; 92 else { 93 add=add_(l+1,r); 94 now=cal(l,r,add); 95 ans=max(ans,now); 96 } 97 } 98 } 99 printf("%lld\n",ans); 100 } 101 return 0; 102 }