第一次做BC呀,本来以为会报零的,做了56分钟A了第一题 然后就没有然后了。
贴一下第一次A的代码。
/* 0.组合数 1. 2016-05-14 19:56:49 */ #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int T,m; ]; ][]; /* long long c(int m,int n) { return f[m]*f[m-n]/f[n]; }*/ void init(int n,int m) { long long i,j; memset(c,,sizeof(c)); ;i<=m;i++) c[][i]=c[][i]=; ;i<=m;i++) c[i][i]=; ;i<=n;i++) c[i][]=; ;i<=n;i++) { ;j<=m;j++) { if(i!=j) c[i][j]=(c[i-][j]+c[i-][j-]); } } /* for(int i=0;i<=30;i++) { c[0][i]=0;c[i][0]=0; } */ } int main() { /* f[0]=0,f[1]=1; for(int i=2;i<=30;i++) { f[i]=f[i-1]*i; } */ init(,); /* for(int i=0;i<=30;i++) for(int j=0;j<=30;j++) cout<<"i="<<i<<"j="<<j<<" c[i]="<<c[i][j]<<endl; */ scanf("%d",&T); while(T--) { scanf("%d",&m); ;i<=m;i++) scanf("%d",&a[i]); sort(a+,a+m+); /* for(int i=1;i<=m;i++) cout<<a[i]<<" "; cout<<endl;*/ ,sumeven=; ;i<=m;i+=) { //从m个里面挑i个 c(m-1,i-1)*a[] for(int j=m;j>=i;j--) { //cout<<sumodd<<" a["<<m-j+1<<"]="<<a[m-j+1]<<" c["<<j-1<<"]["<<i-1<<"]="<<c[i-1][j-1]<<endl; sumodd+=a[m-j+]*c[j-][i-]; } } ;i<=m;i+=) { for(int j=m;j>=i;j--) { sumeven+=a[m-j+]*c[j-][i-]; } } cout<<sumodd-sumeven<<endl; } }
还以为自己很机智,写了个组合数。
后来看了题解才明白过来,答案就是max(ai)。
其实就是整理了一下上面的思路,你想昂,对于某个数ai,以它为最小元素的集合,一共会有2的k-1次个(ai是A中第k大的数)。相当于是比他大的k-1个数组成一个集合,一共有2的k-1次个集合,每个集合再补上元素ai即可。那么所以奇偶互相抵消,直至k=1时只有一个元素了。即最大的那个元素,即max(ai)。
剩下四题一个都看不懂题解 水平太次了。
不过,组合数的写法要学习一下。
组合数 c(m,n)=m! / [ (m-n)!*n! ]
组合数中c(0,n)和c(m,0)都是1!!!这里面 规定了0!=1。
void init(int n,int m) { long long i,j; memset(c,,sizeof(c)); ;i<=m;i++) c[][i]=c[][i]=; ;i<=m;i++) c[i][i]=; ;i<=n;i++) c[i][]=; ;i<=n;i++) { ;j<=m;j++) { if(i!=j) c[i][j]=(c[i-][j]+c[i-][j-]); } } }