Codeforces Round #308 (Div. 2)

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 }
A

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 }
B

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 }
C(法1)

法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 }
C(法2)

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 }
D(法1)

法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 }
D(法2)

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 }
E

猜你喜欢

转载自www.cnblogs.com/HDUjackyan/p/8955339.html