hdu5734 Acperience
题意:说了一大堆,求求和(wi - x * bi),使和最小,wi已知,x非负数,bi取-1或1
题解:列出二次方程,初中知识各种变就行
最后答案是(n * 求和(wi^2) - (求和(wi*bi))^2)
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
LL x,sum1=0,sum2=0;
for(int i=0;i<n;i++){
scanf("%I64d",&x);
sum1+=(LL)x*x;
sum2+=abs(x);
}
LL ans1=(LL)n*sum1-sum2*sum2;
LL ans2=(LL)n;
//cout<<ans1<<' '<<ans2<<endl;
printf("%I64d/%I64d\n",ans1/__gcd(ans1,ans2),ans2/__gcd(ans1,ans2));
}
return 0;
}
hdu5738 Eureka
题意:问有多少个点集合,点集合里面有三点共线
题解:每次选择相对最下左的点,考虑这个点上右方的点,保存斜率就好
需要注意的是,可能有点的坐标相同
LL exp(LL a, LL b, LL c){
LL ans = 1, temp;
a = a % c;
temp = a;
while(b){
if(b&1){
ans = ans * temp % c;
}
temp = temp * temp % c;
b /= 2;
}
return ans;
}
struct point {
LL x, y;
bool operator<(const point&x)const{
if(this->x==x.x)
return this->y<x.y;
else
return this->x<x.x;
}
}p[1010];
bool cmp (point a, point b){
if(a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}
map <point, LL> m1;
map <point, LL> m2;
int main(){
int t,n;
cin>>t;
while(t--){
cin>>n;
m1.clear();
m2.clear();
for(int i=0;i<n;i++){
cin>>p[i].x>>p[i].y;
}
sort(p,p+n,cmp);
LL ans = 0;
for(int i=0;i<n;i++){
if(m2[p[i]])
continue;
m1.clear();
for(int j=i+1;j<n;j++){
LL x = p[j].x - p[i].x;
LL y = p[j].y - p[i].y;
if(x < 0){
x = -x;
y = -y;
}
LL temp = __gcd(x, abs(y));
if(x!=0 && y!=0){
if(x == 0)
y = 1;
if(y == 0)
x = 1;
}
if(temp){
x /= temp;
y /= temp;
}
point tt;
tt.x = x;
tt.y = y;
m1[tt]++;
}
LL ll;
point pp;
pp.x=0;pp.y=0;
LL ll1 = m1[pp];
for(map<point, LL>::iterator it = m1.begin();it != m1.end();it ++){
if(it->first.x == 0 && it->first.y == 0){
ll = exp(2, it->second + 1, mod);
ll = ll - it->second - 2;
ans += ll;
ans %= mod;
}
else {
ll = exp(2, it->second, mod);
ll--;
ans += (ll*(exp(2, ll1+1, mod)-1));
ans %= mod;
}
}
m2[p[i]] = 1;
}
ans %= mod;
cout<<ans<<endl;
}
return 0;
}
hdu5742 It's All In The Mind
题意:数列,有些数未知,递减,求最大(a[1] + a[2]) / 总和
题解:贪心,使a[1] + a[2]尽可能大,总和尽可能小
int main(){
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
int x,y;
if(m==0 || n==2){
printf("1/1\n");
continue;
}
memset(a,-1,sizeof(a));
for(int i=0;i<m;i++){
cin>>x>>y;
a[x]=y;
}
if(a[1]==-1 && a[2]==-1){
a[1]=100;
a[2]=100;
}
else if(a[1]==-1){
a[1]=100;
}
else if(a[2]==-1){
a[2]=a[1];
}
int temp=0;
for(int i=n;i>=3;i--){
if(a[i]==-1){
a[i]=temp;
}
else {
temp=a[i];
}
}
int ans1=a[1]+a[2],ans2=0;
for(int i=1;i<=n;i++){
ans2+=a[i];
}
printf("%d/%d\n",ans1/__gcd(ans1,ans2),ans2/__gcd(ans1,ans2));
}
return 0;
}
hdu5744 Keep On Movin
题意:n个字符,每个字符有ai个,可以组成x个回文串,问所有回文串中最短的最大值是多少
题解:最大化最小值,第一想法,二分
仔细想想,其实不用二分,如果一个字符有奇数个,那么必须要在某个串的中间放一个,如果是偶数,随便添加进去就可以,找到有多少奇数个,剩下的往两边分配就好
int a[100010];
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int sum=0,sum1=0;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
if(a[i]&1){
sum++;
a[i]--;
}
sum1+=a[i];
}
if(sum<=0){
cout<<sum1<<endl;
}
else {
cout<<sum1/2/sum*2+1<<endl;
}
}
return 0;
}