昨天晚上打的这场有点颓啊,B题因为double的精度问题差点卡全场,C题有个小bug一直没找出来。赛后看了一眼D,比前几道都简单。。。最无语的还是B题了,怎么验数据都对。最后10分钟的时候,抱着破罐破摔的心态,把double改掉再次交上去,神奇AC,接着又找到了C的bug。10分钟内极限AC两题,刺激。。。
A题
题目链接:http://codeforces.com/problemset/problem/1027/A
题意:判断是否通过变换可以得到回文串。
容易想到,从两边开始搜索,如果两个字母一样就不去管它,若不一样,再看一下是否可以变成一样的。。。
代码:
#include
using namespace std;
typedef long long ll;
char a[1010];
bool ok(int a,int b)
{
if(a+1==b-1)
return true;
if(a-1==b+1)
return true;
return false;
}
int main()
{
int t;
int n,len;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%s",a+1);
int flag=1;
for(int i=1;i<=n;i++)
{
if(a[i]==a[n-(i-1)])
continue;
else
{
if(ok(a[i],a[n-(i-1)]))
continue;
else
{
flag=0;
break;
}
}
}
if(flag==1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
B题
题意:按题目中所示规律填数,询问每个格子(x,y)中的数是什么。
大致思路就是统计每行有几个数,在询问的格子之前有多少行,自己随便推推就行了。在这里我分了两种情况,一种是n为奇数,1种是n为偶数。两种其实差不多,在处理奇数时因为每行的数不一定相同,需要特殊考虑一下,不算太难。
不过请注意!!!在数很大做乘法时不要使用double,昨天因为这个精度问题被卡了很久。。。
代码:(比赛时写的,有点丑,见谅。。。)
#include
using namespace std;
typedef long long ll;
int main()
{
ll n,q;
ll x,y;
ll ans;
scanf("%lld%lld",&n,&q);
for(int i=1;i<=q;i++)
{
scanf("%lld%lld",&x,&y);
if(n%2==0)
{
if((x+y)%2==0)
{
ans=((n*(x-1))/2+(y+1)/2);
}
else
{
ans=((n*n)/2+n*(x-1)/2+(y+1)/2);
}
}
else
{
if((x+y)%2==0)
{
if(x%2==1)
ans=(n*(x-1))/2+(y+1)/2;
else
ans=(n*(x-1))/2+(y+1)/2+1;
}
else
{
ans=((n*n+1)/2)+n*(x-1)/2+ceil((y+1)/2);
}
}
printf("%lld\n",ans);
}
return 0;
C题
题意:给你一些木棒,选出其中四根拼成矩形,并要求p*p/s最小(p为周长,s为面积)。
首先如果 要是一个长度的木棒达到四根,显然选这个长度。如果没有的话,将所有出现两次的木棒都加入vector中,从小到大排序。根据均值不等式,b/a最小时为所求解,那么我们就看相邻两根就可以了,从中挑出b/a最小的即可。。。
不过这道题T有1e6组,如果每次都memset,总复杂度是1e10,emmmm。。。可还是能过的。。。
代码:
#include
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
int a[maxn];
int cnt[10001];
vector v;
int past[maxn];
template
inline bool scan_d(T &ret)
{
char c;
int sgn;
if (c = getchar(), c == EOF)
{
return 0; //EOF
}
while (c != '-' && (c < '0' || c > '9'))
{
c = getchar();
}
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9')
{
ret = ret * 10 + (c - '0');
}
ret *= sgn;
return 1;
}
template
inline void print_d(T x)
{
if (x > 9)
{
print_d(x / 10);
}
putchar(x % 10 + '0');
}
int main()
{
int t;
int n;
int r1,r2,len;
double cha;
double res;
scanf("%d",&t);
while(t--)
{
v.clear();
scan_d(n);
int flag=0;
int rec;
// for(int i=1;i<=10000;i++)
// {
// if(cnt[i])
// cnt[i]=0;
// }
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)
{
scan_d(a[i]);
// scanf("%d",&a[i]);
cnt[a[i]]++;
if(cnt[a[i]]==4)
{
flag=1;
rec=a[i];
}
else if(cnt[a[i]]==2)
v.push_back(a[i]);
}
if(flag==1)
{
printf("%d %d %d %d\n",rec,rec,rec,rec);
}
else
{
sort(v.begin(),v.end());
len=v.size();
cha=1e6;
for(int i=0;i
D题
有n个房间,每个房间放捕鼠夹有一个费用,老鼠每一秒从一个房间跑到另一个房间(可以自环),求要抓住老鼠最小花费。
这道题比赛时根本没看 ,后来看了一下,发现是道板子题。
首先Tarjin缩点,这样只要在终点处放老鼠夹就好了。在终点的强连通分量中可能有多个房间,选择费用最小的一个即可。。。
代码:
#include
using namespace std;
const int MAXN = 200010;
const int MAXM = 200010;
typedef long long ll;
int a[MAXN];
struct Edge
{
int to, next;
}edge[MAXM];
int Outdegree[MAXN];
int Indegree[MAXN];
int head[MAXN], tot;
int Low[MAXN], DFN[MAXN], Stack[MAXN], Belong[MAXN];
int Index, top;
int scc;
bool Instack[MAXN];
int num[MAXN];
vector ans;
vector Have[MAXN];
void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
return ;
}
void Tarjan(int u)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for (int i = head[u]; i != -1; i = edge[i].next)
{
v = edge[i].to;
if (!DFN[v])
{
Tarjan(v);
if (Low[u] > Low[v])
{
Low[u] = Low[v];
}
}
else if (Instack[v] && Low[u] > DFN[v])
{
Low[u] = DFN[v];
}
}
if (Low[u] == DFN[u])
{
scc++;
do
{
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc;
Have[scc].push_back(v);
num[scc]++;
}
while (v != u);
}
return ;
}
ll solve(int N)
{
memset(DFN, 0, sizeof(DFN));
memset(Instack, false, sizeof(Instack));
memset(num, 0, sizeof(num));
Index = scc = top = 0;
for (int i = 1; i <= N; i++)
{
if (!DFN[i])
{
Tarjan(i);
}
}
for(int i=1;i<=N;i++)
{
int v;
for (int j=head[i];j!=-1;j=edge[j].next)
{
v=edge[j].to;
if(Belong[i]!=Belong[v])
{
Outdegree[Belong[i]]++;
Indegree[Belong[v]]++;
}
}
}
for(int i=1;i<=scc;i++)
{
if(Outdegree[i]==0)
ans.push_back(i);
}
int len=ans.size();
int len2;
ll res=0;
int cur;
ll tem;
for(int i=0;i