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