A. Playing with Paper
解法用辗转相除法,一边求出最大公约数,一边求出可分割的正方形的数量。
#include<stdio.h>
#include<math.h>
using namespace std;
typedef long long ll;
ll ans=0;
ll gcd(ll a,ll b)
{
if(b==0) return a;
else
{
ans+=a/b;
return gcd(b,a%b);
}
}
int main()
{
ll a,b;
scanf("%I64d%I64d",&a,&b);
gcd(a,b);
printf("%I64d
",ans);
return 0;
}
B. Error Correct System
用二维数组标记一下转换表再查找就可以啦
a[i][j]表示字符i转换为字符j的第一个位置
如果a[i][j]和a[j][i]都有需要转换的话,就交换这两个位置,否则查找如a[i][j],a[j][k]的形式交换,否则不能交换。
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;
int len;
char s1[200005],s2[200005];
int a1[26][26];
int main()
{
int i,j,ii;
memset(a1,-1,sizeof(a1));
scanf("%d",&len);
getchar();
gets(s1);
gets(s2);
int k=0;
for(i=0;i<len;i++)
{
if(s1[i]!=s2[i])
{
a1[s1[i]-'a'][s2[i]-'a']=i;
k++;
}
}
int ans1=-1,ans2=-1;
/*for(i=0;i<len;i++)
{
if(a1[i]&&a2[i])
{
ans1=a1[i];
ans2=a2[i];
}
}*/
for(i=0;i<26;i++)
{
for(j=i+1;j<26;j++)
{
if(a1[i][j]!=-1&&a1[j][i]!=-1)
{
ans1=a1[i][j];ans2=a1[j][i];
break;
}
}
if(j<26) break;
}
if(ans1!=-1)
{
printf("%d
",k-2);
printf("%d %d
",ans1+1,ans2+1);
}
else
{
for(i=0;i<26;i++)
{
for(j=0;j<26;j++)
{
if(a1[i][j]!=-1)
{
for(ii=0;ii<26;ii++)
{
if(a1[j][ii]!=-1)
{
ans1=a1[i][j];
ans2=a1[j][ii];
break;
}
}
if(ii<26) break;
}
}
if(j<26) break;
}
if(ans1!=-1)
{
printf("%d
",k-1);
printf("%d %d
",ans1+1,ans2+1);
}
else
{
printf("%d
",k);
printf("-1 -1
");
}
}
return 0;
}
C. Glass Carving
本题要使用特殊的数据结构。
维护横向和纵向的最大宽度,查询时想乘即可。
#include<stdio.h>
#include<math.h>
#include<set>
#include<map>
using namespace std;
set<int> H,V;
map<int,int> HH,VV;
int main()
{
int w,h,n,z;
char c;
scanf("%d%d%d",&w,&h,&n);
H.insert(0);
H.insert(h);
V.insert(0);
V.insert(w);
HH[h]=1;
VV[w]=1;
while(n--)
{
int w;
getchar();
scanf("%c%d",&c,&z);
if(c=='H')
{
H.insert(z);
{
int l,r;
set<int>::iterator it;
it=H.find(z);
it--;
l=*it;
it++;
it++;
r=*it;
HH[r-l]--;
if(HH[r-l]==0)
{
HH.erase(r-l);
}
HH[z-l]++;
HH[r-z]++;
printf("%I64d
",(long long)(HH.rbegin()->first) *(VV.rbegin()->first) );
}
}
else
{
V.insert(z);
{
int l,r;
set<int>::iterator it;
it=V.find(z);
it--;
l=*it;
it++;
it++;
r=*it;
VV[r-l]--;
if(VV[r-l]==0)
{
VV.erase(r-l);
}
VV[z-l]++;
VV[r-z]++;
printf("%I64d
",(long long)(HH.rbegin()->first) *(VV.rbegin()->first) );
}
}
}
return 0;
}
D. Clique Problem
将问题转换,每个点的x和w值可以转换成区间(x-w,x+w),然后求出不想交的区间的最大个数即答案。
求法是贪心,每次都选择右边界最小且和之前的区间不想交的区间即可。
#include<stdio.h>
#include<math.h>
#include<map>
#include<algorithm>
using namespace std;
typedef pair<int,int> P;
P p[200005];
int main()
{
int len,i,x,w;
scanf("%d",&len);
for(i=0;i<len;i++)
{
scanf("%d%d",&x,&w);
p[i].first=x+w;
p[i].second=x-w;
}
int to=-1000000005,ans=0;
sort(p,p+len);
for(i=0;i<len;i++)
{
if(p[i].second>=to)
{
ans++;
to=p[i].first;
}
}
printf("%d
",ans);
return 0;
}
E. Data Center Drama
图论题。没A。。
先判断图是否存在欧拉回路,若不存在则补充边,(度为奇数个的点要补充)。
求出图的欧拉回路,然后顺着路径翻转编号为奇数(或偶数)的边,最后如果总边数是奇数个,就在出发点加一个自环。