五年前做这题的时候卡了好久,试了好多方法都是WA。一直以为是数据出错了,没想到五年之后的今天竟然把这题AC了……
这题思路很简单,就是复分析里的柯西积分公式或者留数。把被积函数写成z^{-1}, z^{-2}和(z-z_0)^{-1}的线性组合然后用柯西积分公式即可。当然|z_0|<R和|z_0|>=R要分开讨论,因为前者需要考虑0和z_0两个点,而后者只要考虑0一个点。当然,|z_0|=R时我感觉积分是发散的,不过根据样例把这种情况跟|z_0|>R放一起就好了。
最后是一些细节问题,特别是最后的输出。比方说如果约分后的结果是0.0000+0.0000i,那么我们应该输出0.0000,也就是虚数位要删去;又比方说1.0000-1.0000i不能输出成1.0000+-1.0000i。诸如此类。
以下是代码。
//#include<bits/stdc++.h>
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<math.h>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=500005;
const double pi=acos(-1.0);
int a,b,c,d,r,x,y;
int T;
double rx,ry;
int main()
{
int i,j;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d %d %d %d %d",&a,&b,&c,&d,&x,&y,&r);
rx=ry=0;
if(x*x+y*y>=r*r)
{
ll rrx=-b*1LL*x*(x*x+y*y)-c*1LL*(x*x-y*y);
ll rry=-b*1LL*y*(x*x+y*y)-c*1LL*2*x*y;
//cout<<rrx<<" "<<rry<<endl;
rx=rrx*2*pi/(d*1LL*(x*x+y*y))/(x*x+y*y);
ry=rry*2*pi/(d*1LL*(x*x+y*y))/(x*x+y*y);
//cout<<rx<<" "<<ry<<endl;
swap(rx,ry);swap(rrx,rry);
if(ll(fabs(rx*10000)+0.5)==0) rrx=0;
if(ll(fabs(ry*10000)+0.5)==0) rry=0;
if(rrx==0&&rry==0) printf("0.0000\n");
else if(rry==0) printf("%.4lf\n",rx);
else if(rrx==0) printf("%.4lfi\n",ry);
else printf("%.4lf%c%.4lfi\n",rx,ry>0?'+':'-',fabs(ry));
//else printf("%.4lf+%.4lfi\n",rx,ry);
}
else
{
if(a==0) printf("0.0000\n");
else printf("%.4lfi\n",2*pi*a/d);
}
}
return 0;
}