第九次新生排位赛

来源:互联网 发布:android和linux的关系 编辑:程序博客网 时间:2024/05/28 05:14

第一题

错了不计其数遍,一个是因为long long 另一个是忘了初始化

时间限制 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.

输入样例

41 1 2 2

输出样例

4hintfor 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.
#include <iostream>#include <cstdio>#include <cmath>#include <queue>#include <algorithm>#include <cstring>using namespace std;long long a[100005];long long sum[100005];int b[100005];int numsum[100005];long long d[100005];long long ans;int main(){    //freopen("data.txt", "r", stdin);    int n;    while(~scanf("%d", &n))    {        for (int i=0; i<n; i++)        {            scanf("%lld", &a[i]);        }        sort(a, a+n);//即使是long long 也是会自己排序的,如果多加一个cmp,慢了好几百秒        long long temp = 0;//这里忘记改long long 又错了好几遍        int mark = 0;        b[0] = 1;        temp = d[0] = a[0];//a[0]可能是负值,所以以第一项为基础值最好        numsum[0] = 1;        for (int i=1; i<n; i++)        {            if (a[i]>d[mark])            {                sum[mark] = temp;                numsum[mark] = i;                mark++;                d[mark] = a[i];                b[mark] = 0;            }            b[mark]++;            temp += a[i];        }        ans = 0;        for (int i=mark; i>0; i--)        {            ans += (numsum[i-1]*d[i]-sum[i-1])*b[i];        }        printf("%lld\n", ans);    }    return 0;}



#include <iostream>#include <cstdio>#include <cmath>#include <queue>#include <algorithm>#include <cstring> using namespace std; long long a[100005];long long sum[100005];int b[100005];int numsum[100005];long long d[100005];long long ans;bool cmp(long long a, long long b){    return a<b;}int main(){    //freopen("data.txt", "r", stdin);    int n;    while(~scanf("%d", &n))    {      for (int i=0; i<n; i++)    {        scanf("%lld", &a[i]);        b[i] = 0;        d[i] = 0;        sum[i] = 0;        numsum[i] = 0;//这一块没有初始化又错了好几遍    }    sort(a, a+n, cmp);    long long tot = 0;    int mark = 0;    tot = a[0];    b[0] = 1;    d[0] = a[0];    sum[0] = tot;    numsum[0] = 1;     for (int i=1; i<n; i++)    {        if (a[i]>tot)        {            tot = a[i];            mark++;            d[mark] = a[i];            sum[mark] = sum[mark-1];            numsum[mark] = numsum[mark-1];        }         b[mark]++;        sum[mark] += a[i];        numsum[mark]++;    }    ans = 0;    for (int i=mark; i>0; i--)    {        ans += (numsum[i-1]*d[i]-sum[i-1])*b[i];    }    printf("%lld\n", ans);     }    return 0;}

#include <iostream>#include <cstdio>#include <cmath>#include <queue>#include <algorithm>#include <cstring> using namespace std;int father[10005];long long num[10005];struct data{    int u, v, c;}a[100005];bool cmp(data a1, data a2){    return a1.c<a2.c;}int seek(int k){    while (father[k]!=k)        k = father[k];    return k;}int main(){    //freopen("data.txt", "r", stdin);    int t;    scanf("%d", &t);    while(t--)    {        int n, m;        scanf("%d %d", &n, &m);        for (int i=0; i<m; i++)        {            scanf("%d %d %d", &a[i].u, &a[i].v, &a[i].c);        }        sort(a, a+m, cmp);        for (int i=1; i<=n; i++)         {             father[i] = i;             num[i] = 1;         }        int t1, t2;        long long ans = 0;        for (int i=0; i<m; i++)        {            t1 = seek(a[i].u);            t2 = seek(a[i].v);            if (t1!=t2)            {                father[max(t1, t2)] = min(t1, t2);                int tk = a[i].c;                if (tk==0) tk=1;                ans += 2*num[t1]*num[t2]*tk;                num[min(t1, t2)] += num[max(t1, t2)];            }        }         printf("%lld\n", ans);    }    return 0;}

第三题 用后缀数组最快,我还没学,下面也是个很别扭的KMP .next 勉强看看,以后学会了补上


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

题目描述

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

输入格式

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

 

输出格式

每组答案输出一行。

输入样例

2aabbaabbaaabcde

输出样例

60


#include <iostream>#include <cstdio>#include <cmath>#include <queue>#include <algorithm>#include <cstring> using namespace std; int main(){    //freopen("data.txt", "r", stdin);    int t;    scanf("%d", &t);    char a[2005];    char b[2005];    int next[2005];     while(t--)    {        int maxn = 0;        scanf("%s", a);        int len = strlen(a);        for (int s=0; s<len; s++)        {            for (int m=s; m<=len; m++)                b[m-s] = a[m];            int len1 = strlen(b);            memset(next, -1, sizeof next);            next[0] = -1;            int k = -1, j = 0;            while (b[j]!=0)            {                while (k!=-1&&b[k]!=b[j])                    k = next[k];                j++;                k++;                if (b[k]==b[j])                    next[j] = next[k];                else                    next[j] = k;            }             for (int i=0; i<=len1; i++)                maxn = max(maxn, next[i]);        }        printf("%d\n", maxn);    }    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 12 03 1 0

输出样例

10hint:第一组样例所示地面为:..*其中‘.‘表示空地,’*‘表示花花草草,一种方案可以铺满。


/*如果现在只有一个格子或者两个格子,那么我们放砖块的方法数是很好计算的
所以代码是从最右下角开始往上递推,
假如其余所有格子都放满了,现在要放最后一个,有几种方法
一直到,假如一个格子都没放,现在要从第一个开始放有几种
中间过程就是,假如其余前面格子都放满了,现在要从当前位置开始放一直到放满有几种
虽然1*2的格子我们在考虑放在某个点的时候有四个朝向,但是基于对称原理,我们只考虑往右和往下
因为往上的方向,可以看做上面格子往下,
为了构造连续推导关系,我们需要考虑的是前面都放满了,处理完当前(i, j)点后,我们会转移到接下来的哪个状态
(s是个二进制表示的状态,是一行待定的可能的状态)
 s表示的是一行,但是这是特殊的一行,这一行可能不在同一直线上,它们的共同点是它们的上面都必须放满了
 如果它是1,表示它被已经排好的格子占用了,(注意它们相互间不占用,带排的这一行没有主动关系),
 如果为0,表示没有被占用


当前状态的方法数设为dp[cur][s],下一个状态的方法数为dp[next][s'],显然dp[cur][s]等于所有可能的dp[next][s']的和
两个状态之间的转移其实只涉及到了它自己,它右边,它下面


当前点(i, j)
s中如果这个点是1,表示它被左边或上面的格子占用了,那么它肯定不会占用它下面的格子,下一个状态中,
它下面的点也是j位置是必须是0(0表示没有被占用)才有可能是它转移过去的,


s中如果这个点是0,表示可以自由放1*2格子,可以向右延伸,也可以向下延伸,
向右,那么右边这个格子(j+1)在位置上其实也是下一状态的(j+1), 首先它在当前状态必须是0,表示没被它上面占用
其次在下一状态必须是1,不会再铺,(表示已之前被铺,受限制)
向下,当前肯定是0; 下一状态也必须要为1了。


花其实好考虑的,加点判断进去就好了
*/

#include <iostream>#include <cstdio>#include <cmath>#include <queue>#include <algorithm>#include <cstring>#define maxn 1000000007using namespace std;bool a[15][15];int dp[2][1<<10];//int main(){    //freopen("in.txt", "r", stdin);    //freopen("out.txt", "w", stdout);    int n, m, k;     while (~scanf("%d %d %d", &n, &m, &k))    {        memset(a, 0, sizeof a);        int tx, ty;        for (int i=0; i<k; i++)        {            scanf("%d %d", &tx, &ty);            a[tx][ty] = true;        }        if ((m*n-k)&1)        {            printf("0\n");            continue;        }        int cur = 0;        int next = 1;        //memset(dp[next], 0, sizeof (long long)*(1<<m));//一开始出错是因为改了long long却没有改 sizeof (long long) 其实最后发现也不需要用long long        memset(dp, 0,sizeof dp);        dp[next][0] = 1;        for (int i=n-1; i>=0; i--)            for (int j=m-1; j>=0; j--)            {                for (int k=(1<<m)-1; k>=0; k--)//千万注意优先级                {                    dp[cur][k] = 0;                    if ((k>>j&1)||(a[i][j]))                        dp[cur][k] = dp[next][k&(~(1<<j))];                    else                    {                        if (((j+1)<m)&&!(k>>(j+1)&1)&&(!a[i][j+1]))                            dp[cur][k] = (dp[cur][k]+dp[next][k|(1<<(j+1))])%maxn;                        if (!a[i+1][j])                            dp[cur][k] = (dp[cur][k]+dp[next][k|(1<<j)])%maxn;                     }                }                swap(next, cur);//最后的结果保存在next里面            }         printf("%d\n", dp[next][0]);    }      return 0;}


0 0
原创粉丝点击