2009 Multi-University Training Contest 1 - Host by TJU

【HDU2817】 - A sequence of numbers——快速幂+水题

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description

Xinlv wrote some sequences on the paper a long time ago, they might be arithmetic or geometric sequences. The numbers are not very clear now, and only the first three numbers of each sequence are recognizable. Xinlv wants to know some numbers in these sequences, and he needs your help.

Input

The first line contains an integer N, indicting that there are N sequences. Each of the following N lines contain four integers. The first three indicating the first three numbers of the sequence, and the last one is K, indicating that we want to know the K-th numbers of the sequence.

You can assume 0 < K <= 10^9, and the other three numbers are in the range [0, 2^63). All the numbers of the sequences are integers. And the sequences are non-decreasing.

Output

Output one line for each test case, that is, the K-th number module (%) 200907.

Sample Input

2
1 2 3 5
1 2 4 5

Sample Output

5
16

给你数列的前三项,求第k个数是多少?数列只有等差和等比两种情况。则分别判断和计算一下,可能会爆long long ,注意处理。

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
const LL Mod = 200907;

int n;

LL a[3],k;

LL Pow(LL n,LL m) {
    LL ans  = 1;
    while(m) {
        if(m&1) ans = (ans*n)%Mod;
        n = (n*n)%Mod;
        m>>=1;
    }
    return ans;
}

int main() {
    scanf("%d",&n);
    for(int i = 0;i<n;i++) {
        for(int i = 0;i<3;i++) scanf("%lld",&a[i]);
        scanf("%d",&k);
        LL ans;
        if(a[1]%a[0] == 0 && a[2]%a[1] == 0 && a[1]/a[0]  == a[2]/a[1]) {
            LL q = a[1]/a[0];
            LL st = Pow(q,k-1);
            a[0] %= Mod;
            ans = (a[0]*st)%Mod;
        }
        else {
            LL d = (a[1] -a[0])%Mod;
            d = ((k-1)*d)%Mod;
            ans = (a[0]%Mod+d)%Mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

【HDU2818】-Building Block——并查集

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description

John are playing with blocks. There are N blocks (1 <= N <= 30000) numbered 1…N。Initially, there are N piles, and each pile contains one block. Then John do some operations P times (1 <= P <= 1000000). There are two kinds of operation:

M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command.
C X : Count the number of blocks under block X

You are request to find out the output for each C operation.

Input

The first line contains integer P. Then P lines follow, each of which contain an operation describe above.

Output

Output the count for each C operations in one line.

Sample Input

6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4

Sample Output

1
0
2

给你一些石子,有两种操作,一种将某一个编号的石子所在的石碓放在另一个编号的石碓上面,另一个操作是询问某一编号的石子下面有多少个石子。并查集的简单应用,每个石子维护两个信息,一个是自己所在石碓的石子的数量,一个是自己下面石子的数量。

#include <bits/stdc++.h>

using namespace std;

const int maxn = 30100;

int pre[maxn];
int sum[maxn];
int num[maxn];
int Find(int x) {
    if(pre[x] == x) {
        return x;
    }
    else {
        int Fa = pre[x];
        int s = Find(Fa);
        sum[x]+=sum[Fa];
        pre[x] = s;
        return s;
     }
}

void Union(int x,int y) {
    int Fx = Find(x);
    int Fy = Find(y);
    if(Fx!=Fy) {
        sum[Fx] = num[Fy];
        num[Fy] += num[Fx];
        pre[Fx] = Fy;
    }
}

int main(){
    int m;
    char op[2];
    int u,v;
    while(~scanf("%d",&m)) {
        for(int i = 0;i<maxn;i++) pre[i] = i,num[i] = 1,sum[i] = 0;
        while(m--) {
            scanf("%s",op);
            if(op[0] == 'M') {
                scanf("%d %d",&u,&v);
                Union(u,v);
            }
            else {
                scanf("%d",&u);
                Find(u);
                printf("%d\n",sum[u]);
            }
        }
    }
    return 0;
}

【HDU2819】-Swap——二分图

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Special Judge

Problem Description

Given an N*N matrix with each entry equal to 0 or 1. You can swap any two rows or any two columns. Can you find a way to make all the diagonal entries equal to 1?

Input

There are several test cases in the input. The first line of each test case is an integer N (1 <= N <= 100). Then N lines follow, each contains N numbers (0 or 1), separating by space, indicating the N*N matrix.

Output

For each test case, the first line contain the number of swaps M. Then M lines follow, whose format is “R a b” or “C a b”, indicating swapping the row a and row b, or swapping the column a and column b. (1 <= a, b <= N). Any correct answer will be accepted, but M should be more than 1000.

If it is impossible to make all the diagonal entries equal to 1, output only one one containing “-1”.

Sample Input

2
0 1
1 0
2
1 0
1 0

Sample Output

1
R 1 2
-1

给你一个n*n的矩阵,问是否能够经过一些行的交换或者列的交换使得主对角线为1。对于一行都有对应的交换的列,那么就相当于每一行和对应的列进行匹配。转化为二分图的问题

#include <bits/stdc++.h>

using namespace std;

const int maxn = 110;

int n;
int G[maxn][maxn];
int row[maxn];
bool vis[maxn];

int dfs(int s) {
    for(int i = 1; i<=n; i++) {
        if(G[s][i] && !vis[i]) {
            vis[i] = true;
            if(!row[i] || dfs(row[i])) {
                row[i] = s;
                return 1;
            }
        }
    }
    return 0;
}
vector<pair<int,int> >vi;
int main() {
    while(~scanf("%d",&n)) {
        for(int i = 1; i<=n; i++) {
            for(int j = 1; j<=n; j++) scanf("%d",&G[i][j]);
        }
        memset(row,0,sizeof(row));
        int ans = 0;
        for(int i = 1; i<=n; i++) {
            memset(vis,false,sizeof(vis));
            ans+=dfs(i);

        }
        if(ans<n) {
            printf("-1\n");
        } else {
            vi.clear();
            for(int i = 1; i<=n; i++) {
                int j =1;
                for(; j<=n&&row[j]!=i; j++);
                if(i==j)continue;
                vi.push_back(make_pair(i,j));
                swap(row[i],row[j]);
            }
            printf("%d\n",vi.size());
            for(int i = 0; i<vi.size(); i++) printf("C %d %d\n",vi[i].first,vi[i].second);
        }
    }
    return 0;
}

【HDU2822】-Dogs——优先队列

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description

Prairie dog comes again! Someday one little prairie dog Tim wants to visit one of his friends on the farmland, but he is as lazy as his friend (who required Tim to come to his place instead of going to Tim’s), So he turn to you for help to point out how could him dig as less as he could.

We know the farmland is divided into a grid, and some of the lattices form houses, where many little dogs live in. If the lattices connect to each other in any case, they belong to the same house. Then the little Tim start from his home located at (x0, y0) aim at his friend’s home ( x1, y1 ). During the journey, he must walk through a lot of lattices, when in a house he can just walk through without digging, but he must dig some distance to reach another house. The farmland will be as big as 1000 * 1000, and the up left corner is labeled as ( 1, 1 ).

Input

The input is divided into blocks. The first line in each block contains two integers: the length m of the farmland, the width n of the farmland (m, n ≤ 1000). The next lines contain m rows and each row have n letters, with ‘X’ stands for the lattices of house, and ‘.’ stands for the empty land. The following two lines is the start and end places’ coordinates, we guarantee that they are located at ‘X’. There will be a blank line between every test case. The block where both two numbers in the first line are equal to zero denotes the end of the input.

Output

For each case you should just output a line which contains only one integer, which is the number of minimal lattices Tim must dig.

Sample Input

6 6
..X…
XXX.X.
….X.
X…..
X…..
X.X…
3 5
6 3

0 0

Sample Output

3

Hint

Hint: Three lattices Tim should dig: ( 2, 4 ), ( 3, 1 ), ( 6, 2 ).

给你一个图,有起点和终点,问从起点到终点的经过最少’.’。

#include <bits/stdc++.h>
#define PII pair<int,int>
using namespace std;
const int INF = 0x3f3f3f3f;
int n,m;
char str[1100][1100];
int x,y,x2,y2;
int dir[][2] = {{1,0},{-1,0},{0,1},{0,-1}};
bool vis[1100][1100];
int dis[1100][1100];
bool ok(int x,int y) {
    return (x>=0&&x<n&&y>=0&&y<m);
}

struct node {
    int x,y,step;
    node(){}
    node(int _x,int _y,int _step):x(_x),y(_y),step(_step){}
    bool operator < (const node &a)const {
        return step > a.step;
    }
};
int bfs() {
    memset(vis,false,sizeof(vis));
    memset(dis,INF,sizeof(dis));
    priority_queue<node>Q;
    dis[x][y] = 0;
    vis[x][y] = true;
    Q.push(node(x,y,0));
    while(!Q.empty()) {
        node u = Q.top(); Q.pop();
        node v;
        vis[u.x][u.y] = false;
        for(int i = 0;i<4;i++) {
            v.x = u.x + dir[i][0];
            v.y = u.y + dir[i][1];
            if(ok(v.x,v.y)) {
                int st = str[v.x][v.y] == 'X'?0:1;
                if(dis[v.x][v.y] > dis[u.x][u.y]+st) {
                    dis[v.x][v.y] = dis[u.x][u.y]+st;
                    v.step = u.step+st;
                    if(!vis[v.x][v.y])
                    {
                        vis[v.x][v.y] = true;
                        Q.push(v);
                    }
                }
            }
        }
    }
    return dis[x2][y2];
}
int main(){
    while(~scanf("%d %d",&n,&m)&&(n+m)) {
        for(int i = 0 ;i<n;i++) {
            scanf("%s",str[i]);
        }
        scanf("%d %d %d %d",&x,&y,&x2,&y2);
        x--;y--;x2--;y2--;
        int ans = bfs();
        printf("%d\n",ans);
    }
    return 0;

}

【HDU2824】-The Euler function——欧拉数

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description

The Euler function phi is an important kind of function in number theory, (n) represents the amount of the numbers which are smaller than n and coprime to n, and this function has a lot of beautiful characteristics. Here comes a very easy question: suppose you are given a, b, try to calculate (a)+ (a+1)+….+ (b)

Input

There are several test cases. Each line has two integers a, b (2

Output

Output the result of (a)+ (a+1)+….+ (b)

Sample Input

3 100

Sample Output

3042

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
const int maxn = 3000001;
LL sum[maxn];
void GetPhi() {
    sum[1] = 1;
    for(int i = 2;i<maxn;i++) {
        if(!sum[i]) {
            for(int j = i;j<maxn;j+=i) {
              if(!sum[j]) sum[j] = j;
              sum[j] = sum[j]/i*(i-1);
            }
        }
        sum[i]+=sum[i-1];
    }
}

int main(){
    GetPhi();
    int a,b;
    while(~scanf("%d %d",&a,&b)) {
        printf("%lld\n",sum[b]-sum[a-1]);
    }
    return 0;
}

【HDu2825】-Wireless Password——AC自动机+状态压缩

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description

Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless network in the building. Liyuan did not know the password of the network, but he got some important information from his neighbor. He knew the password consists only of lowercase letters ‘a’-‘z’, and he knew the length of the password. Furthermore, he got a magic word set, and his neighbor told him that the password included at least k words of the magic word set (the k words in the password possibly overlapping).

For instance, say that you know that the password is 3 characters long, and the magic word set includes ‘she’ and ‘he’. Then the possible password is only ‘she’.

Liyuan wants to know whether the information is enough to reduce the number of possible passwords. To answer this, please help him write a program that determines the number of possible passwords.

Input

There will be several data sets. Each data set will begin with a line with three integers n m k. n is the length of the password (1<=n<=25), m is the number of the words in the magic word set(0<=m<=10), and the number k denotes that the password included at least k words of the magic set. This is followed by m lines, each containing a word of the magic set, each word consists of between 1 and 10 lowercase letters ‘a’-‘z’. End of input will be marked by a line with n=0 m=0 k=0, which should not be processed.

Output

For each test case, please output the number of possible passwords MOD 20090717.

Sample Input

10 2 2
hello
world
4 1 1
icpc
10 0 0
0 0 0

Sample Output

2
1
14195065

给你m个串,问组成长度为n的串中有k个所给串的方案数
我们定义dp[i][j][k]表示长度为i,在自动机j个节点,个数为k的方案数,其中k由于最大有1-个所以可以状态压缩。

#include <bits/stdc++.h>

using namespace std;
const int mod = 20090717;
const int maxn = 120;
typedef long long LL;
int tr[maxn][26],top;
int fail[maxn];
char str[maxn];
int n,m,k;
int flag[maxn];
int dp[26][maxn][1<<10];
void Insert(int Index) {
    int len = strlen(str);
    int x = 0 ;
    for(int i = 0; i<len; i++) {
        int st = str[i] - 'a';
        if(!tr[x][st]) tr[x][st] = ++top;
        x = tr[x][st];
    }
    flag[x] |= 1<<Index;
}
void GetFail() {
    memset(fail,0,sizeof(fail));
    queue<int>Q;
    for(int i = 0; i<26; i++ ) if(tr[0][i]) Q.push(tr[0][i]);
    while(!Q.empty()) {
        int u = Q.front(); Q.pop();
        for(int i = 0; i<26; i++) {
            if(tr[u][i]) {
                Q.push(tr[u][i]);
                fail[tr[u][i]] = tr[fail[u]][i];
                flag[tr[u][i]] |= flag[tr[fail[u]][i]];
            }
            else tr[u][i] = tr[fail[u]][i];
        }
    }
}
int cnt(int s) {
    int ans = 0;
    for(int i = 0; i<m; i++) if((s>>i)&1) ans++;
    return ans;
}
int main() {
    while(~scanf("%d %d %d",&n,&m,&k)&&(n||m||k)) {
        memset(tr,0,sizeof(tr));
        memset(flag,0,sizeof(flag));
        top = 0;
        for(int i = 0; i<m; i++) {
            scanf("%s",str);
            Insert(i);
        }
        GetFail();
        memset(dp,0,sizeof(dp));
        dp[0][0][0] = 1;
        for(int i = 0; i<n; i++) {
            for(int j = 0; j<=top; j++) {
                for(int s = 0; s<(1<<m); s++) {
                    if(dp[i][j][s] ==0 )continue;
                    for(int t = 0; t<26; t++) (dp[i+1][tr[j][t]][s|flag[tr[j][t]]] +=dp[i][j][s])%=mod;
                }
            }
        }
        int ans = 0;
        for(int i = 0; i<=top; i++) {
            for(int j = 0; j<(1<<m); j++) {
                if(cnt(j)< k) continue;
                (ans+=dp[n][i][j])%=mod;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(2009 Multi-University Training Contest 1 - Host by TJU)