Problem
You are given two vectors v1=(x1,x2,...,xn) and v2=(y1,y2,...,yn). The scalar product of these vectors is a single number, calculated as x1y1+x2y2+...+xnyn.
Suppose you are allowed to permute the coordinates of each vector as you wish. Choose two permutations such that the scalar product of your two new vectors is the smallest possible, and output that minimum scalar product.
Input
The first line of the input file contains integer number T - the number of test cases. For each test case, the first line contains integer number n . The next two lines contain n integers each, giving the coordinates of v 1 and v 2 respectively.Output
For each test case, output a line
Case #X: Ywhere X is the test case number, starting from 1, and Y is the minimum scalar product of all permutations of the two given vectors.
Limits
Small dataset
T = 1000
1 ≤ n ≤ 8
-1000 ≤ xi, yi ≤ 1000
Large dataset
T = 10
100 ≤ n ≤ 800
-100000 ≤ xi, yi ≤ 100000
Sample
我的代码:
#include <iostream> #include <cstdio> using namespace std; #define LARGE void bubble_sort(__int64* &array,int size); int main() { #ifdef SMALL freopen("a_small.in","r",stdin); freopen("a_samll.out","w",stdout); #endif #ifdef LARGE // freopen("a_large.in","r",stdin); freopen("a_large.out","w",stdout); #endif __int64 * v1; __int64 * v2; //No.2 int T,N; __int64 Y; cin>>T; for(int i=0;i!=T;++i) { cin>>N; v1 = new __int64[N]; v2 = new __int64[N]; Y=0; for(int j=0;j!=N;++j) scanf("%I64d",&v1[j]); for(j=0;j!=N;++j) scanf("%I64d",&v2[j]); bubble_sort(v1,N);//No.1 bubble_sort(v2,N); for(j=0;j!=N;++j) { Y+=v1[j]*v2[N-1-j]; } cout<<"Case #"<<i+1<<": "; printf("%I64d\n",Y); } return 0; } void bubble_sort(__int64* &array,int size) //No.3 { int temp; for(int i=0;i!=size-1;++i) { for(int j=i+1;j!=size;++j) { if(array[j]>array[i]) { temp=array[i]; array[i]=array[j]; array[j]=temp; } } } }
此题说的是,给两个整型数组,要求出这个数组内积的最小值,这个数组内积在题中有定义。此题思路很简单,先对这两个数组进行排序,然后用数组1的最小值乘以数组2的最大值,然后加上数组1的次小值乘以数组2的次大值,依此类推,得到的最终值就是那个内积的最小值。对于此题有两点可以注意下:
No.1 & No.3: 第一点是这个排序算法没有问题,而且在数组指针以引用的形式传递指针的时候,注意写法。这样就可以直接返回对数组的操作。比如int数组,就是写成int* &a.加入int* a是指向此数组的指针。所以可以读成指向a数组指针的引用。这是一点。但是关于排序这里我最想说的是:其实在C++标准库里面有很好的排序函数,在<algorithm>头文件下,sort()函数,具体用法请baidu‘之。那样的话,可以使代码更简洁,对于程序员来讲,可以专注于问题和算法。
No.2: 第二点是此题的小数据其实问题不大,思路很简单,它的乘积不会超过int的表示范围。下面我把数据类型的表示范围贴出来。
For 32-bit and 64-bit compilers, Microsoft Visual C++ recognizes the types shown in the table below. Note that the following type also have unsigned forms:
Type Name | Bytes | Other Names | Range of Values |
---|---|---|---|
int |
4 |
signed |
–2,147,483,648 to 2,147,483,647 |
unsigned int |
4 |
unsigned |
0 to 4,294,967,295 |
__int8 |
1 |
char |
–128 to 127 |
unsigned __int8 |
1 |
unsigned char |
0 to 255 |
__int16 |
2 |
short, short int, signed short int |
–32,768 to 32,767 |
unsigned __int16 |
2 |
unsigned short, unsigned short int |
0 to 65,535 |
__int32 |
4 |
signed, signed int, int |
–2,147,483,648 to 2,147,483,647 |
unsigned __int32 |
4 |
unsigned, unsigned int |
0 to 4,294,967,295 |
__int64 |
8 |
long long, signed long long |
–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
unsigned __int64 |
8 |
unsigned long long |
0 to 18,446,744,073,709,551,615 |
bool |
1 |
none |
false or true |
char |
1 |
none |
–128 to 127 by default 0 to 255 when compiled with /J |
signed char |
1 |
none |
–128 to 127 |
unsigned char |
1 |
none |
0 to 255 |
short |
2 |
short int, signed short int |
–32,768 to 32,767 |
unsigned short |
2 |
unsigned short int |
0 to 65,535 |
long |
4 |
long int, signed long int |
–2,147,483,648 to 2,147,483,647 |
unsigned long |
4 |
unsigned long int |
0 to 4,294,967,295 |
long long |
8 |
none (but equivalent to __int64) |
–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
unsigned long long |
8 |
none (but equivalent to unsigned __int64) |
0 to 18,446,744,073,709,551,615 |
enum |
varies |
none |
See Remarks. |
float |
4 |
none |
3.4E +/- 38 (7 digits) |
double |
8 |
none |
1.7E +/- 308 (15 digits) |
long double |
same as double |
none |
same as double |
wchar_t |
2 |
__wchar_t |
0 to 65,535 |
可以看到在32bit机器上,int类型和long类型都是表示一样的数据范围,在10位整数。小数据没有问题,但是大数据有问题,你看大数据的范围。它的最大可能乘积到了11位了,所以要用到long long类型或者叫做__int64,它能表示19位整数。符合我们题目要求。
具体在各种不同的编译器下面使用这种长整数类型,请看下表:
zz from http://www.byvoid.com/blog/c-int64/
在C/C++中,64为整型一直是一种没有确定规范的数据类型。现今主流的编译器中,对64为整型的支持也是标准不一,形态各异。一般来说,64位整型的定义方式有long long和__int64两种(VC还支持_int64),而输出到标准输出方式有printf(“%lld”,a),printf(“%I64d”,a),和cout << a三种方式。
本文讨论的是五种常用的C/C++编译器对64位整型的支持,这五种编译器分别是gcc(mingw32),g++(mingw32),gcc(linux i386),g++(linux i386),Microsoft Visual C++ 6.0。可惜的是,没有一种定义和输出方式组合,同时兼容这五种编译器。为彻底弄清不同编译器对64位整型,我写了程序对它们进行了评测,结果如下表。
变量定义 | 输出方式 | gcc(mingw32) | g++(mingw32) | gcc(linux i386) | g++(linux i386) | MicrosoftVisual C++ 6.0 |
---|---|---|---|---|---|---|
long long | “%lld” | 错误 | 错误 | 正确 | 正确 | 无法编译 |
long long | “%I64d” | 正确 | 正确 | 错误 | 错误 | 无法编译 |
__int64 | “lld” | 错误 | 错误 | 无法编译 | 无法编译 | 错误 |
__int64 | “%I64d” | 正确 | 正确 | 无法编译 | 无法编译 | 正确 |
long long | cout | 非C++ | 正确 | 非C++ | 正确 | 无法编译 |
__int64 | cout | 非C++ | 正确 | 非C++ | 无法编译 | 无法编译 |
long long | printint64() | 正确 | 正确 | 正确 | 正确 | 无法编译 |
上表中,正确指编译通过,运行完全正确;错误指编译虽然通过,但运行结果有误;无法编译指编译器根本不能编译完成。观察上表,我们可以发现以下几点:
zz from http://blog.csdn.net/zhlynn/archive/2009/03/28/4032152.aspx
64位整数全解(增补板)
64位整形引起的混乱主要在两方面,一是数据类型的声明,二是输入输出。
首先是如果我们在自己机器上写程序的话,情况分类如下:
(1) 在win下的VC6.0里面,声明数据类型的时候应该写作
__int64 a;
输入输出的时候用 %I64d
scanf(”%I64d”,&a);
printf(”%I64d”,a);
(2) 在linux下的gcc/g++里面,数据类型声明写作
long long a;
输入输出时候用 %lld
(3) 在win下的其它IDE里面[包括高版本Visual Studio],数据类型声明用上面两种均可
输入输出用 %I64d
注意上面红色粗体,那个64前面是大写的I,不是小写的l。至于为什么不是long的首字母,而是大写的I,我也是试过出了错才知道的。
使用C++标准库定义的模板类vector和函数来解决
#include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { freopen("a_large.in","r",stdin); freopen("a_large.out","w",stdout); int T,n; __int64 temp,Y; cin>>T; for(int i=0;i!=T;++i) { cin>>n; vector<__int64> v1,v2; for(int j=0;j!=n;++j) { scanf("%I64d",&temp); v1.push_back(temp); } for(j=0;j!=n;++j) { scanf("%I64d",&temp); v2.push_back(temp); } sort(v1.begin(),v1.end()); sort(v2.begin(),v2.end()); Y=0; for(j=0;j!=n;++j) { Y+=v1[j]*v2[n-j-1]; } cout<<"Case #"<< (i+1) <<": "; printf("%I64d\n",Y); } return 0; }