Hdu 2015 Multi-University Training Contest9

1004

题面

Problem Description
Rhason Cheung had a simple problem, and asked Teacher Mai for help. But Teacher Mai thought this problem was too simple, sometimes naive. So she ask you for help.

Teacher Mai has m functions f1,f2,⋯,fm:{1,2,⋯,n}→{1,2,⋯,n}(that means for all x∈{1,2,⋯,n},f(x)∈{1,2,⋯,n}). But Rhason only knows some of these functions, and others are unknown.

She wants to know how many different function series f1,f2,⋯,fm there are that for every i(1≤i≤n),f1(f2(⋯fm(i)))=i. Two function series f1,f2,⋯,fm and g1,g2,⋯,gm are considered different if and only if there exist i(1≤i≤m),j(1≤j≤n),fi(j)≠gi(j).

Input
For each test case, the first lines contains two numbers n,m(1≤n,m≤100).

The following are m lines. In i-th line, there is one number −1 or n space-separated numbers.

If there is only one number −1, the function fi is unknown. Otherwise the j-th number in the i-th line means fi(j).

Output
For each test case print the answer modulo 109+7.

Sample Input
3 3
1 2 3
-1
3 2 1

Sample Output
1

Hint
The order in the function series is determined. What she can do is to assign the values to the unknown functions.

题意

给m(100)个函数,和函数值域定义域整数的最大值n(100)。
函数为: f1,f2,f3...fm{1,2,...n}{1,2,...n}
这个式子的意思是,函数 fm 的定义域为: {1,2,...n} ,值域也为: {1,2,...n}
现在要求一个固定序列的 f1,f2,f3...fm ,使得对于每个1<= i <= n,都有 f1(f2(f3...fm(i)))=i
现在给出的数据中,第i行第j列代表 fi(j)=x
比如样例:
3 3
1 2 3
-1
3 2 1
代表有3行3列的数据:
第一行: f1(1)=1,f1(2)=2,f1(3)=3
第二行未知;
第三行: f3(1)=3,f3(2)=2,f3(3)=1
由此推出第二行应该只有一种选择: f2(1)=3,f2(2)=2,f2(3)=1 。才能使得对于每个i,上面那个等式都成立。
然而样例并没有什么用。

解析

统计总共有几个-1,即有多少函数是未知的。
如果没有-1,说明整个映射关系是完整的,只要去判断当前这个映射关系是否满足题意就行了,行输出1,不行0。一开始我直接输出0了,后来看了讨论区那段羞射的问答:

“-1的数量为0的时候要判断吗”
“随你咯” -admin

如果当一行当中出现了重复的数,那么这个方案是无论如何都不能满足每个映射回去都为i的,输出0。

排除了上两种方案以后,最后的答案就是:
(n!)cnt1 ,这个式子瞎猜的,只要拿出一层未知的-1来调整方案,余下的都是全排。
然后就好了。

代码

#pragma comment(linker, "/STACK:1677721600")
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cassert>
#include <iostream>
#include <algorithm>
#define pb push_back
#define mp make_pair
#define LL long long
#define lson lo,mi,rt<<1
#define rson mi+1,hi,rt<<1|1
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a,b) memset(a,b,sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)

using namespace std;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double ee = exp(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 100 + 10;
const double pi = acos(-1.0);
const LL iinf = 0x3f3f3f3f3f3f3f3f;

int readT()
{
    char c;
    int ret = 0,flg = 0;
    while(c = getchar(), (c < '0' || c > '9') && c != '-');
    if(c == '-') flg = 1; else ret = c ^ 48;
    while( c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c ^ 48);
    return flg ? - ret : ret;
}

LL fact[maxn];

void factTable()
{
    fact[0] = 1;
    for (int i = 1; i < maxn; i++)
    {
        fact[i] = (fact[i - 1] * i) % mod;
    }
}

LL pow_mod(LL a, LL n)
{
    if (n == 0)
        return 1;
    LL x = pow_mod(a, n >> 1);
    LL ans = (LL)x * x % mod;
    if (n % 2)
        ans = ans * a % mod;
    return ans;
}

int a[maxn][maxn];
bool vis[maxn];
int n, m;

int f(int i, int x)
{
    return x == 1 ? a[x][i] : f(a[x][i], x - 1);
}

bool ok()
{
    for (int i = 1; i <= n; i++)
    {
        if (f(i, m) != i)
            return false;
    }
    return true;
}

int main()
{
    #ifdef LOCAL
    FIN;
    #endif // LOCAL
    factTable();
    while (~scanf("%d%d", &n, &m))
    {
        mem0(a);
        bool flag = false;
        LL cnt = 0;
        for (int i = 1; i <= m; i++)
        {
            mem0(vis);
            for (int j = 1; j <= n; j++)
            {
                a[i][j] = readT();
//                cout << a[i][j] << endl;
                if (j == 1 && a[i][1] == -1)
                {
                    cnt++;
                    break;
                }
                if (vis[a[i][j]])
                {
                    flag = true;
                }
                else
                {
                    vis[a[i][j]] = true;
                }
            }
        }
        if (flag)
        {
            puts("0");
        }
        else
        {
            if (cnt == 0)
            {
                puts(ok() ? "1" : "0");
                continue;
            }
            LL ans = pow_mod(fact[n], cnt - 1) % mod;
            printf("%I64d\n", ans);
        }
    }
    return 0;
}

1005

题面

Problem Description
A sequence b1,b2,⋯,bn are called (d1,d2)-arithmetic sequence if and only if there exist i(1≤i≤n) such that for every j(1 ≤j < i ),bj+1=bj+d1 and for every j(i ≤ j < n),bj+1=bj+d2.

Teacher Mai has a sequence a1,a2,⋯,an. He wants to know how many intervals [l, r](1 ≤ l ≤ r ≤ n) there are that al,al+1,⋯,ar are (d1,d2)-arithmetic sequence.

Input
There are multiple test cases.

For each test case, the first line contains three numbers n,d1,d2(1≤n≤105,|d1|,|d2|≤1000), the next line contains n integers a1,a2,⋯,an(|ai|≤109).

Output
For each test case, print the answer.

Sample Input

5 2 -2
0 2 0 -2 0
5 2 3
2 3 3 3 3

Sample Output

12
5

题意

首先是关于(d1,d2)性的定义:
给定一个数列 b1,b2,b3...bn
如果存在一个 i(1≤i≤n),
使得每一个 j(1 ≤j < i),都有 bj+1=bj+d1
并且每一个 j (i ≤ j < n), bj+1=bj+d2
通俗来说,就是前一段等差数列,后一段等差数列。
现在给大小为n(1e5)的数列,给两个公差d1,d2,|d1|,|d2|≤1000,判断满足(d1,d2)性的[l, r]区间有多少个。

解析

如果满足d1=d2,那么,直接算每个连续的长度len,然后高斯求和len就好了。
如果d1 != d2,那么只要计算从左到右有多少个数是d1等差数列 乘上 从右到左右多少个数是d2等差数列即可。

没判断d1=d2,然后在算dpl,dpr的时候又把d2写成了d1。。。
我蛋都碎了。( ▼-▼ )

代码

#pragma comment(linker, "/STACK:1677721600")
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cassert>
#include <iostream>
#include <algorithm>
#define pb push_back
#define mp make_pair
#define LL long long
#define lson lo,mi,rt<<1
#define rson mi+1,hi,rt<<1|1
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a,b) memset(a,b,sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)

using namespace std;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double ee = exp(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 1e6 + 10;
const double pi = acos(-1.0);
const LL iinf = 0x3f3f3f3f3f3f3f3f;

int readT()
{
    char c;
    int ret = 0,flg = 0;
    while(c = getchar(), (c < '0' || c > '9') && c != '-');
    if(c == '-') flg = 1; else ret = c ^ 48;
    while( c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c ^ 48);
    return flg ? - ret : ret;
}

int a[maxn];
LL dpl[maxn];
LL dpr[maxn];

int main()
{
    #ifdef LOCAL
    FIN;
    #endif // LOCAL
    int n, d1, d2;
    while (~scanf("%d%d%d", &n, &d1, &d2))
    {
        mem0(dpl);
        mem0(dpr);
        mem0(a);
        for (int i = 1; i <= n; i++)
        {
            a[i] = readT();
        }

        a[0] = inf;
        a[n + 1] = inf;
        if (d1 == d2)
        {
            LL ans = 0;
            LL len = 1;
            for (int i = 2; i <= n + 1; i++)
            {
                if (a[i] == a[i - 1] + d1)
                {
                    len++;
                }
                else
                {
                    ans += len * (len + 1) / 2;
                    len = 1;
                }
            }
//            ans += len * (len + 1) / 2;
            printf("%I64d\n", ans);
            continue;
        }

        for (int i = 1; i <= n; i++)
        {
            if (a[i - 1] + d1 == a[i])
            {
                dpl[i] = dpl[i - 1] + 1;
            }
        }
        for (int i = n; i >= 1; i--)
        {
            if (a[i + 1] - d2 == a[i])
            {
                dpr[i] = dpr[i + 1] + 1;
            }
        }

        LL ans = 0;
        for (int i = 1; i <= n; i++)
        {
            ans += (dpl[i] + 1) * (dpr[i] + 1);
//            cout << dpl[i] << " " << dpr[i] <<endl;
        }
//        cout  << endl;
        printf("%I64d\n", ans);
    }
    return 0;
}

1007

题面

Problem Description
Teacher Mai is in a maze with n rows and m columns. There is a non-negative number in each cell. Teacher Mai wants to walk from the top left corner (1,1) to the bottom right corner (n,m). He can choose one direction and walk to this adjacent cell. However, he can’t go out of the maze, and he can’t visit a cell more than once.

Teacher Mai wants to maximize the sum of numbers in his path. And you need to print this path.

Input
There are multiple test cases.

For each test case, the first line contains two numbers n,m(1≤n,m≤100,n∗m≥2).

In following n lines, each line contains m numbers. The j-th number in the i-th line means the number in the cell (i,j). Every number in the cell is not more than 104.

Output
For each test case, in the first line, you should print the maximum sum.

In the next line you should print a string consisting of “L”,”R”,”U” and “D”, which represents the path you find. If you are in the cell (x,y), “L” means you walk to cell (x,y−1), “R” means you walk to cell (x,y+1), “U” means you walk to cell (x−1,y), “D” means you walk to cell (x+1,y).

Sample Input

3 3
2 3 3
3 3 3
3 3 2

Sample Output

25
RRDLLDRR

题意

给一个n * m(100 * 10)的数字迷宫,数字全为正数,要求从(1,1)点出发到(n,m)点,上下左右移动并且每个数字只能经过一次,使得获得的数字的和最大。并输出路径。

首先n和m当中无论哪个,只要出现奇数那么整张数字迷宫都遍历就是答案了;
然后就是n和m都为偶数的时候,可以发现去掉的都是下图中0标记的地方,并且只去掉当中的一个。可以试一试,如果去掉除了0外的其他地方,必定要多删掉多个0标记的地方。
比如6 * 6的数字迷宫:

1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1

删掉的点是以上0标记的地方中最值最小的点。
得到贪心策略以后,就是输出路径有点麻烦,于是让队友开始敲,我继续想1003。

..
..
..
然后这交了好多发都wa。
原因一:当删除点为一行中最后的那个点,多输出了一个R。
原因二:…第二个if完了以后没有输出sum。。。
函数名足以表达心情。

代码

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <list>
#include <map>
#include <set>

#define ULL unsigned long long
#define PI 3.1415926535
#define INF 0x3f3f3f3f
#define LL long long
#define eps 1e-8

using namespace std;

const int maxn = 110;

int maze[maxn][maxn];

void print(int l, int p)
{
    if (p == 0)
    {
        for(int i = 1; i< l; ++i)
            printf("R");
        printf("D");
        for(int i = 1; i < l; ++i)
            printf("L");
    }
    else
    {
        for(int i = 1; i < l; ++i)
            printf("L");
        printf("D");
        for(int i = 1; i < l; ++i)
            printf("R");
    }
}

void printl(int m, int p)
{
    if (p == 0)
    {
        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j < 2; ++j)
                printf("%c", i % 2 == 0 ? 'U':'D');
            if (i < m)
                printf("R");
        }
    }
    else
    {
        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j < 2; ++j)
                printf("%c", i % 2 == 0 ? 'D':'U');
            if (i < m)
                printf("R");
        }
    }
}

void fuck(int m, int pos_x, int pos_y)
{
    if (pos_x != 1 && pos_x != 2)
        printf("D");
    pos_x = pos_x  % 2;
    printl(pos_y - 1, 0);
    if (pos_y - 1 == 0 || m == 2 || pos_y == m)
        printf("R");
    else
        printf("RR");
    if(pos_x == 1)
        printl(m - pos_y, 1);
    else
        printl(m - pos_y, 0);
}

int main()
{
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // LOCAL
    int m, n;

    while(~scanf("%d%d", &n, &m))
    {
        int sum = 0;
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j)
            {
                scanf("%d", &maze[i][j]);
                sum += maze[i][j];
            }

        if (n & 1)
        {
            printf("%d\n", sum);
            for (int i = 1; i <= n; ++i)
            {
                for (int j = 1; j < m; ++j)
                    printf("%c", i % 2 == 0 ? 'L':'R');
                if (i < n)
                    printf("D");
            }
            printf("\n");
        }
        else  if (m & 1)
        {
            printf("%d\n", sum);
            for (int i = 1; i <= m; ++i)
            {
                for (int j = 1; j < n; ++j)
                    printf("%c", i % 2 == 0 ? 'U':'D');
                if (i < m)
                    printf("R");
            }
            printf("\n");
        }
        else
        {
            int pos_x = 1, pos_y = 2;
            int min_num = maze[1][2];

            for (int i = 1; i <= n; ++ i)
                for (int j = 1; j <= m; j++)
                {
                    if ((i + j ) & 1)
                    {
                        if (min_num > maze[i][j])
                        {
                            pos_x = i;
                            pos_y = j;
                            min_num = maze[i][j];
                        }
                    }
                }
            sum -= min_num;

            printf("%d\n", sum);
            for(int i = 1; i < (pos_x + 1) / 2; ++i)
            {
                print(m, 0);
                if (i < (pos_x + 1) / 2 - 1)
                    printf("D");
            }
            fuck(m, pos_x, pos_y);
            if (pos_x < n - 1)
                printf("D");
            for(int i = (pos_x + 1)/ 2 + 1; i <= n / 2; ++i)
            {
                print(m, 1);
                if (i < n/ 2 )
                    printf("D");
            }
            printf("\n");
        }
    }
    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值