2014新生暑假个人排位赛09

时间限制 1000 ms  内存限制 65536 KB

题目描述

You are givin an array of integers, and you are to figure out the sum of differences between each pair of integers belonging to the array. SEE THE HINT FOR MORE INFORMATION.

输入格式

There are multiple test cases. The first line contains an integer n(n<=1e5), size of the array. The second line contains n integers, ai(|ai|<=100000), the array.

输出格式

For each case, output one line, the answer.

输入样例

4
1 1 2 2

输出样例

4

hint
for the test case the answer is abs(1-1)+abs(1-2)+abs(1-2)+abs(1-2)+abs(1-2)+abs(2-2)=4.
给一个数列,求两两之间差的绝对值的和。

算一下发现有式子的。


/*
USER_ID: test#wlwlxgg
PROBLEM: 470
SUBMISSION_TIME: 2014-08-01 14:00:58
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
 
using namespace std;
 
int a[100010];
 
int main()
{
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        if(n==1){
            printf("%d\n",a[0]);
            continue;
        }
        sort(a,a+n);
        reverse(a,a+n);
        long long ans=0;
        for(int i=0;i<n;i++)
            ans+=(long long)(n-i-1)*(long long)a[i];
        for(int i=1;i<n;i++)
            ans-=i*(long long)a[i];
        printf("%lld\n",ans);
    }
    return 0;
}


时间限制 1000 ms  内存限制 65536 KB

题目描述

Mays王国的女王大人每天过着自由自在的生活,她最大的乐趣就是给邻国的帅气王子写信。但是最近,Mays王国的叔叔们变得很无聊,他们知道女王大人每次都把信委托给皇家小妹妹快递公司的小妹妹们,于是叔叔们给每一条路都设立了路障,只有小妹妹们给他们表演节目才会让小妹妹们过去。
在每一个路障,都有不同数量的叔叔,只有表演的小妹妹的数量不少与叔叔的数量的时候叔叔才会放她们过去。
可是七夕快要到了,Masy王国的每一个人都在给自己的情人写信。
Mays王国由n个地区组成,一些双向的道路连接着这些地区。注意两个地区之间可能有多条道路相通。
无聊的单身的beegerous已经算出了从一点到另一点送信最少需要的小妹妹的数量,为了表达对世界的不满,他脑补出了小妹妹们给任意两个点之间送信的画面,这样她们一共需要送n*(n-1)次信!如果所有的信件必须同一时间发出,这样每一次快递都需要由不同的小妹妹们来送!这样就会有好多好多小妹妹在Mays王国的道路上忙碌了。
请问,按上述脑补情形,皇家小妹妹快递公司一共需要派出多少小妹妹。

输入格式

输入第一行为数据组数T(T<=10),接下来T组数据,每组第一行为n,m,,2<=n<=10000,1<=m<=100000,表示Mays王国的道路由n个节点组成,接下来m行,每行一组u,v,c表示连接节点u,v的一条无向道路,且路障上有c个叔叔,1<=u,v<=n,0<=c<=100。
输入保证任意两点之间可达。

输出格式

每组数据输出一个数字,表示小妹妹快递公司最少需要派出的小妹妹数量。

输入样例

1
3 3
1 2 1
2 3 1
1 3 3

输出样例

6

hint:
9种送快递的方式及花费为:
1 --> 2:  1
1 --> 3:  1
2 --> 1:  1
2 --> 3:  1
3 --> 1:  1
3 --> 2:  1
答案为6
是上一场的加强版,这个要求求仍意两点间权值最大的边的最小值的权值的和。比赛时以为用spfa怎么样修改一下就可以了,结果没想出来,其实就是kruskal。用并查集去记录每新加的点到父亲节点的数目再乘以最小的权值。


/*
USER_ID: test#wlwlxgg
PROBLEM: 474
SUBMISSION_TIME: 2014-08-03 16:53:44
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#define MAX_E 100010
#define MAX_V 10010
 
using namespace std;
 
struct edge {int u,v,cost;};
edge e[MAX_E];
int n,m;
int father[MAX_V],num[MAX_V];
 
int find(int n){
    if(n==father[n]) return n;
    else return father[n]=find(father[n]);
}
 
void unite(int x,int y){
    x=find(x),y=find(y);
    if(x==y)return ;
    if(num[x]<num[y]){
        father[x]=y;
        num[y]+=num[x];
    }
    else {
        father[y]=x;
        num[x]+=num[y];
    }
}
 
bool cmp(const edge& a,const edge& b){
    return a.cost<b.cost;
}
 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].cost);
            if(e[i].cost==0) e[i].cost=1;
        }
        sort(e,e+m,cmp);
        for(int i=0;i<=n;i++){
            father[i]=i;
            num[i]=1;
        }
        long long ans=0;
        for(int i=0;i<m;i++){
            if(find(e[i].u)!=find(e[i].v)){
                ans+=2*(long long)e[i].cost*(long long)(num[find(e[i].u)])*num[find(e[i].v)];
                unite(e[i].u,e[i].v);
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}


时间限制 6000 ms  内存限制 65536 KB

题目描述

Mays王国的女王大人每天过着自由自在的生活,她最大的乐趣就是给邻国的帅气王子写信。而负责给她送信的就是皇家小妹妹快递公司。
今天负责给女王大人送信的是一个新来的小妹妹,她非常好奇女王大人的信,于是悄悄的把它拆开来看了!但是机智的女王大人早就想到了会有这种情况发生,她和邻国帅气王子的信都是加密过的~
小妹妹研究了一路,她感觉,里面重复比较多的内容应该是有用信息。为了安慰自己的智商,小妹妹希望找到信的一个最长连续的子串,这个子串出现2次或以上。为了能找到的子串尽可能长,小妹妹认为即便出现的2次有一部分重叠也是可以的。

输入格式

输入第一行为数据组数T(T<=10),每组一行字符串str,str中只包含小写字母,且长度不超过2000。

 

输出格式

每组答案输出一行。

输入样例

2
aabbaabbaa
abcde

输出样例

6
0

给你一个字符串,让你求可以重叠的相同字串的最大长度。

后缀数组。这个模板速度好慢的说,



#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#define MAX_N 1000010

using namespace std;

int n,k;
int rank[MAX_N],lcp[MAX_N],sa[MAX_N];
int tmp[MAX_N];
char s[MAX_N];

bool compare_sa(int i,int j){
    if(rank[i]!=rank[j]) return rank[i]<rank[j];
    else {
        int ri = i + k <= n ? rank[i+k] : -1;
        int rj = j + k <= n ? rank[j+k] : -1;
        return ri<rj;
    }
}

void construct_sa(char s[],int sa[]){
    n=strlen(s);
    for(int i=0;i<=n;i++){
        sa[i]=i;
        rank[i]= i < n ? s[i] : -1;
    }
    for(k=1;k<=n;k++){
        sort(sa,sa+n+1,compare_sa);
        tmp[sa[0]]=0;
        for(int i=1;i<=n;i++)
            tmp[sa[i]]=tmp[sa[i-1]]+(compare_sa(sa[i-1],sa[i]) ? 1 : 0);
        for(int i=0;i<=n;i++)
            rank[i]=tmp[i];
    }
}

void construct_lcp(char s[],int sa[],int lcp[]){
    n=strlen(s);
    for(int i=0;i<=n;i++) rank[sa[i]]=i;
    int h=0;
    lcp[0]=0;
    for(int i=0;i<n;i++){
        int j=sa[rank[i]-1];
        if(h>0) h--;
        for(;j+h<n&&i+h<n;h++)
            if(s[j+h]!=s[i+h]) break;
        lcp[rank[i]-1]=h;
    }
}

int main()
{
    int t;
    while(~scanf("%d",&t)){
        scanf("%s",s);
        construct_sa(s,sa);
        construct_lcp(s,sa,lcp);
        int ans=-1;
        for(int i=0;i<n;i++)
            ans=max(ans,lcp[i]);
        printf("%d\n",ans);
    }
    return 0;
}


时间限制 1000 ms  内存限制 65536 KB

题目描述

大家都知道,学校里有很多路在修,修路需要砖块。这一天,Mr.F来到集训队,找学妹去帮忙搬砖块。善良的学长们不忍心让学妹劳动,就争先恐后的帮助学妹搬砖。于是聪明的学妹说,我出一个题,谁答出来谁就能帮我搬砖。
把学校要铺的地面看成是n*m的方格,每一块砖的大小是1*2,学妹想知道有多少种方法可以把这块地铺满。注意地上有可能会有花花草草,有爱心的学妹不忍心砖块把它们压死,所以这些点是不可以铺砖块的。

输入格式

输入多组数据,数据组数不超过20组。每组第一行为三个整数n, m, k,(1<=n, m<=10),k<=n*m,分别代表地面的长宽,以及花花草草的数量。接下来k行,每行一组x,y,表示花花草草的坐标。详细方向见样例。

输出格式

每组输出一个数,即最后的方案数。由于输出会很大,请输出答案mod 1000000007(10^9+7)。

输入样例

3 1 1
2 0

3 1 0

输出样例

1
0

hint:
第一组样例所示地面为:
.
.
*
其中‘.‘表示空地,’*‘表示花花草草,一种方案可以铺满。
状压dp,还不是很懂。


#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int a[11][11];
int dp[2][1<<11];

int main()
{
    int n,m,k;
    while(~scanf("%d%d%d",&n,&m,&k)){
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                a[i][j]=1;
        for(int i=0;i<k;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            a[x][y]=0;
        }
        int *crt=dp[0],*next=dp[1];
        crt[0]=1;
        for(int i=n-1;i>=0;i--){
            for(int j=m-1;j>=0;j--){
                for(int used=0;used<1<<m;used++){
                    if((used>>j&1)||!a[i][j])
                        next[used]=crt[used&~(1<<j)];
                    else  {
                        int res=0;
                        if(j+1<m&&!(used>>(j+1)&1)&&a[i][j+1])
                            res+=crt[used|1<<(j+1)];
                        if(i+1<n&&a[i+1][j])
                            res+=crt[used|1<<j];
                        next[used]=res%1000000007;
                    }
                }
                swap(crt,next);
            }
        }
        printf("%d\n",crt[0]);
    }
    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值