武汉大学校赛(个人总结+补题)

【题意】:
B.Color
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
When Asuho was just a little girl, she has been loving stars, as there are so many romantic stories about old legends and the stars.

Today, as usual, Asuho went to the observatory with her beloved boyfriend, Kogasaka Ming, to see the splendid sky of galaxy. Sitting with Kogasaka shoulder to shoulder, Asuho thought nothing could make her happier.

“Asuho,” Kogasaka called Asuho softly. “I have a question about the Hoshizora(night sky with stars).”

“What’s it?” Asuho answered, happily. “I know everything about the stories, you can ask anything.”

Kogasaka smiled, “You see the stars? Just imagine there are nn distinct stars in the sky while n-1n−1 relationships connect them. Each relationship is between two stars and all stars are connected directly or indirectly. Now you need to divide the nn stars into mm different types. Beware that no two directly connected stars should share the same type and some stars cannot be some types. I want you to tell me how many distinct solutions there could be.”

Suddenly the Stella meteor shower appeared, so the lovers forgot the question and started to admire the beautiful Hoshizora.

Asuho thought it was unbelievable that Kogasaka should ask her such a foolish question which she can’t solve. Of course she didn’t wish to reveal her poor math. So can you help her to tell the answer?

Input

The Input file contains several test cases.

For each case, the first line contains two integers nn (2\le n\le 10^42≤n≤10
​4
​​ ), mm (1\le m\le 201≤m≤20)

The next n-1n−1 lines, each line contains 2 integers x_ix
​i
​​ , y_iy
​i
​​ expressing relationships between the two stars.

The next nn lines, each lines contains m numbers and each of the mm is 0 or 1.

The ii-th number of the jj-th line respect whether jj-th star can be divided into the ii-th type. 1 means it could while 0 means not.

Output

For each test case, output one single line, containing the number of solutions module 10^7+910
​7
​​ +9

Examples

Input 1

4 6
1 2
1 3
1 4
1 1 1 1 1 0
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
Output
1
625
【代码】:

//头文件
int n,m;
int dp[maxn][25];
int c[maxn][25];

struct adjs{int to,next;}ad[maxn<<1];
int head[maxn],adcnt;
inline void adjs_init() {memset(head,-1,sizeof(head)); adcnt=0;}
inline void add_edge(int a,int b) {ad[adcnt].to=b; ad[adcnt].next=head[a]; head[a]=adcnt++;}

void dfs(int u,int fa)
{
    for(int i=1;i<=m;i++) dp[u][i]=c[u][i];
//    cout <<u <<endl;
//    for(int i=1;i<=m;i++) cout <<dp[u][i]; cout <<endl;
    for(int i=head[u];~i;i=ad[i].next)
    {
        int v=ad[i].to;
        if(v==fa) continue;
        dfs(v,u);
        int tot=0;
        for(int j=1;j<=m;j++) tot = (tot+dp[v][j])%MOD;
//        cout <<v <<" " <<tot <<endl;
        for(int j=1;j<=m;j++)
        {
            int now = (tot-dp[v][j])%MOD;
            if(now<0) now+=MOD;

            dp[u][j] = ((LL)dp[u][j]*now)%MOD;
//            if(u==1) cout <<dp[u][j] <<" " <<now <<endl;
        }
    }

}

void work()
{
    while(~scanf("%d%d",&n,&m))
    {
        adjs_init();
        for(int i=1;i<n;i++)
        {
            int x,y; read(x), read(y);
            add_edge(x,y);
            add_edge(y,x);
        }

        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                read(c[i][j]);


        dfs(1,1);

        int tot=0;
        for(int i=1;i<=m;i++) tot = (tot+dp[1][i])%MOD;
        cout <<tot <<endl;
    }
}

//--------------end--------------------

int main()
{
#ifdef yukihana0416
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif // yukihana0416
    work();
    return 0;
}

C. Divide by Six
无解时输出-1s而不是WTF

数据可能有前导零

Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
A positive integer number n is written on a blackboard. It consists of not more than 10^510
​5
​​ digits. You have to transform it into a mogicalnumber by erasing some of the digits, and you want to erase as few digits as possible.

The number is lucky if it consists of at least one digit, doesn’t have leading zeroes and is a multiple of 6. For example, 0, 66,66666 are lucky numbers, and 00, 25, 77 are not.

Write a program which for the given nn will find a mogical number such that nn can be transformed into this number by erasing as few digits as possible. You can erase an arbitraty set of digits. For example, they don’t have to go one after another in the number nn.

Print the length of your answer after the erasing.

If it’s impossible to obtain a lucky number, print -1s.

Input

The first line of input contains nn – a positive integer ( 1\le n \le 10^{100000}1≤n≤10
​100000
​​ ).

Output

Print one number — the number of your lucky number obtained by erasing as few as possible digits. If there is no answer, print -1s.

Example

Input 1

0010456
Output 1

4
Input 2

11
Output 2

-1s
【思路】:
这道题大佬用了动规的思想,然后,我就试着用动规做了下,发现还真可以,当时没发现。
思路:(个人的)(应该和大佬的一样)
解释一下dp[i][j]=x,i代表当前数字的位置,j代表取余6的数(把整个字符串当成一个数,j*10+t进行分段取余),而x代表的是dp[i][j]对应的最大长度。
给dp赋初值的时候,是-INF,这个是防止出现1000的情况,大家可以手动模拟,另外就是状态转移方程,为什么有两个,因为表示当前位置取或不取。
最最重要的一点就是,既然用了动规,就要明白,当前状态就是最优状态。

代码:

const int INF=1e9;
char s[100000+10];
int dp[100000+10][7];
int main()
{

    scanf("%s",s+1);
    int len=strlen(s+1);
    for(int i=0;i<=len;i++)
        for(int j=0;j<6;j++)
        dp[i][j]=-INF;
    int ans=-INF;
    for(int i=1; i<=len; i++) if(s[i]=='0')ans=1;
    for(int i=1; i<=len; i++)
    {
        int t=s[i]-'0';
        if(t!=0)
            dp[i][t%6]=1;
        for(int j=0; j<=5; j++)
            dp[i][j]=max(dp[i-1][j],dp[i][j]);
        for(int j=0; j<=5; j++)
            dp[i][(j*10+t)%6]=max(dp[i-1][j]+1,dp[i][(j*10+t)%6]);
        ans=max(ans,dp[i][0]);
    }
    if(ans>0)
        printf("%d\n",ans);
    else
        printf("-1s\n");
}

D.Events
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
Every year, the ACM/ICPC team will hold many contests, some of them are training while others are school contests.

In the year of 2017, there are nn contests to be held, and at the beginning of year, we plans the time of each contest.

However, as things are changing. Some other events might affect the time of contest and our team leader wants to know some interesting things about the time of some events.

Input

The first line contains an integer nn. (0 < n \le 10^50

int n;
struct Node
{
    LL flag;
    LL now_min,smin;
}T[maxn<<2];

inline void merge(int id)
{
    T[id].now_min=min(T[ls].now_min,T[rs].now_min);
    T[id].smin=min(T[ls].smin,T[rs].smin);
}

void build(int l,int r,int id)
{
    if(l==r)
    {
        T[id].flag=0;
        LL x; read(x);
        T[id].now_min=T[id].smin=x;
        return ;
    }
    int mid=MID(l,r);
    build(lson);
    build(rson);
    merge(id);
}

inline void lazy(int id)
{
    LL x=T[id].flag; T[id].flag=0;
    T[ls].flag+=x; T[rs].flag+=x;
    T[ls].now_min+=x; T[rs].now_min+=x;
    Min(T[ls].smin,min(T[ls].now_min,T[ls].smin));
    Min(T[rs].smin,min(T[rs].now_min,T[rs].smin));
}


void update(LL x,int L,int R,int l,int r,int id)
{
    if(L<=l && r<=R)
    {
        T[id].flag+=x;
        T[id].now_min+=x;
        Min(T[id].smin,T[id].now_min);
        return ;
    }
    lazy(id);
    int mid=MID(l,r);
    if(L<=mid) update(x,L,R,lson);
    if(mid<R) update(x,L,R,rson);
    merge(id);
}

LL query(int L,int R,int l,int r,int id)
{
    if(L<=l && r<=R) return T[id].smin;
    lazy(id);
    int mid=MID(l,r);
    if(R<=mid) return query(L,R,lson);
    if(mid<L) return query(L,R,rson);
    return min(query(L,R,lson),query(L,R,rson));
}

void work()
{
    while(~scanf("%d",&n))
    {
        build(1,n,1);
        int q; read(q);
        while(q--)
        {
            int l,r;
            LL x;
            read(l), read(r), read(x);

            update(x,l,r,1,n,1);
            LL ans=query(l,r,1,n,1);
            printf("%lld\n",ans);
        }
    }
}

//--------------end--------------------

int main()
{
#ifdef yukihana0416
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif // yukihana0416
    work();
    return 0;
}

E. Lost in WHU
【题目来源】http://acm.whu.edu.cn/olive/problem/642
【题意】
给出一个无向图,有n个点,并且有m条边相连,每走一步需要一个单位时间,现在给出一个deadline作为限制时间,问,在限制时间内,从1到n有多少种走法。
【思路】
萌新的我当初只想到了广搜,但是呢,deadline的范围是小于等于10^9,这可不是广搜能够解决的问题,自学过离散的现在想法是矩阵快速幂,在一个图里,用邻接矩阵存下点与点相互之间的信息,0,代表没有联通,1代表连通,根据矩阵乘法,若:
A矩阵:
0 1 0 1 0
0 0 0 0 1
0 1 0 1 0
0 0 0 0 1
1 0 1 0 0
那么A²矩阵:
0 0 0 0 2
1 0 1 0 0
0 0 0 0 2
1 0 1 0 0
0 2 0 2 0
那么A³矩阵:
2 0 2 0 0
0 2 0 2 0
2 0 2 0 0
0 2 0 2 0
0 0 0 0 4
从v₂到v₃长度为1,2,3的路分别有0,1,2条。
邻接矩阵的次方代表长度,也就是限制时间,而a(i,j)对应的点,代表vi到vj的路的条数。
【代码】

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<limits.h>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int mod=1e9+7;
const double esp=1e-5;
typedef unsigned long long ll;
typedef long long LL;
int n,m,q;
struct mat
{
    LL a[110][110];
};
mat operator*(mat s,mat t)
{
    mat r;
    mem(r.a,0);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            for(int k=1; k<=n; k++)
            {
                r.a[i][j]+=s.a[i][k]*t.a[k][j];
                if(r.a[i][j]>=mod)
                    r.a[i][j]%=mod;
            }
        }
    }
    return r;
}
void print(mat s)
{
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            printf("%d ",s.a[i][j]);
        }
        printf("\n");
    }
}
mat pow_mat(mat base)
{

    mat ans;
    mem(ans.a,0);
    for(int i=1; i<=n; i++)
        ans.a[i][i]=1;
    while(q)
    {
        if(q&1)
            ans=ans*base;
        base=base*base;
        q>>=1;
    }
    return ans;

}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        mat ans;
        mem(ans.a,0);
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
           if(x!=n) ans.a[x][y]=1;
           if(y!=n) ans.a[y][x]=1;
        }
//        print(ans);
        scanf("%d",&q);
        ans.a[n][n]=1;
        ans=pow_mat(ans);
        printf("%lld\n",ans.a[1][n]);
    }
}

F. Soul Artist
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
Last year, there were three soul artist in the team Abysswatcher. They were all addicted to painting, even when they were on the train. One day, they want to paint a paper. In ii-th step, they choose a core grid (x_i, y_i)(x
​i
​​ ,y
​i
​​ ) and paint all the grid near it (the Manhattan distance distance between the core and other grids are no more than r_ir
​i
​​ ). After some operates, they want to know the maximum times they painted the same grid.

Input

Three integers n, m, tn,m,t(1 \le n, m \le 2000, 1 \le t \le 2 \times 10^51≤n,m≤2000,1≤t≤2×10
​5
​​ )in one line. nn and mm represent the length and the width of the paper. tt represents the times they painted.

In the following tt lines, the ii-th contains three non-negative integers x_i, y_i, r_ix
​i
​​ ,y
​i
​​ ,r
​i
​​ (1 \le x_i - r_i, x_i + r_i \le n1≤x
​i
​​ −r
​i
​​ ,x
​i
​​ +r
​i
​​ ≤n, 1 \le y_i - r_i, y_i + r_i \le m1≤y
​i
​​ −r
​i
​​ ,y
​i
​​ +r
​i
​​ ≤m).

Output

Two integers in one line, represent the maximum times they painted the same grid and the number of such grid.

Examples

Input 1

6 6 4
2 2 1
2 3 1
3 2 0
3 4 2
Output 1

3 2
Note

The sample looks like this. The “Manhattan distance” of two points A, BA,B equals to |A_x - B_x| + |A_y - B_y|∣A
​x
​​ −B
​x
​​ ∣+∣A
​y
​​ −B
​y
​​ ∣.

\ 1 2 3 4 5 6 -> x
1 1 1 1
2 1 2 3 2 1
3 3 2 1 1 1
4 1 1 1
5 1
6
|
v
y
代码:

int f[4444][4444],n,m,q;
int main(void)
{
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    #endif
    scanf("%d%d%d",&n,&m,&q);
    for (int i=0;i<q;i++) {
        int x,y,R;
        scanf("%d%d%d",&x,&y,&R);
        int r = x+y+R, l = x+y-R, u = x-y+R+m, d = x-y-R+m;
        //printf("l = %d, r = %d, d = %d, u = %d\n",l,r,d,u);
        f[u][r]++;
        f[u][l-1]--;
        f[d-1][r]--;
        f[d-1][l-1]++;
    }
//    for (int i=1;i<=n+m;i++) {
//        for (int j=1;j<=n+m;j++) printf("%2d ",f[i][j]);
//        puts("");
//    }
    for (int i=1;i<=n+m;i++) for (int j=1;j<=n+m;j++)
        f[i][j] = f[i][j] + f[i-1][j] + f[i][j-1] - f[i-1][j-1];
//    for (int i=1;i<=n+m;i++) {
//        for (int j=1;j<=n+m;j++) printf("%2d ",f[i][j]);
//        puts("");
//    }
//    for (int i=1;i<=n;i++) {
//        for (int j=1;j<=m;j++) {
//            printf("%d ",f[i+j][i-j+m]);
//        }
//        puts("");
//    }
    int ans = 0,cnt = 0;
    for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) {
        if (f[i+j][i-j+m] > ans) {
            ans = f[i+j][i-j+m];
            cnt = 1;
        } else if (f[i+j][i-j+m] == ans) {
            cnt++;
        }
    }
    printf("%d %d\n",ans,cnt);
    return 0;
}

G.Time Limit Exceeded
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
Everyone hates the verdict “Time Limit Exceeded” or “TLE”. However, sometimes, we can’t come up with a “elegant” solution which is clear and fast.

Our problem setter also hates “TLE”, but he is dumb and can only work out what a problem is. He can’t really solve it. We called him “Zui Qiang Xuan Shou”

One day, he got a problem, again, he said “I got it! It is **”, he spoke so fast that no one knew what he said. Luckily, he typed his solution—



#include <stdio.h>
int main()
{
  int n;
  int *vec;
  scanf("%d", &n);
  vec = malloc(sizeof(int) * n);
  for (int i = 0; i < n; i++)
  {
    int t;
    scanf("%d", &t);
    vec.push_back(t);
  }
  long long ans = 0;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n - 1; j++)
      if (vec[j] > vec[j+1])
      {
        ans++;
        swap(vec[j], vec[j+1]);
      }
  printf("%lld\n", ans);
  return 0;
}

He said that it should get AC small cases, but he might receive “Time Limit Exceeded”.

As he clicked the “submit” button, the network is down. So he went to the dinning hall and ask you to correct his solution.

Your program should output exact same things as the program listed above.

Input

The format of input should make the program work if we don’t care about the time.

In the input file, all numbers are positive integers and no more than 10^610
​6
​​ .

Output

You should output what the program outputs if the time is unlimited.

Examples

Input 1

5
1 2 3 4 5
Output 1

0
Input 2

6
1 2 3 4 5 6
Output 2

0
代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <string>
#define LL long long
using namespace std;
int f[1001000],a[1001000],b[1001000];
int tot,n;
inline int lowbit(int x) {return x&-x;}
void add(int p) {
    for (;p<=tot;p+=lowbit(p)) f[p]++;
}
LL query(int p) {
    LL sum = 0;
    for (;p;p-=lowbit(p)) sum += f[p];
    return sum;
}
int main(void)
{
    //#ifdef LOCAL
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    //#endif
    scanf("%d",&n);
    for (int i=0;i<n;i++) {
        scanf("%d",&a[i]);
        b[i] = a[i];
    }
    sort(b,b+n);
    tot = unique(b,b+n)-b;
    LL ans = 0;
    for (int i=0;i<n;i++)
    {
        int pos = lower_bound(b,b+tot,a[i])-b + 1;
        ans += i-query(pos);
        add(pos);
    }
    printf("%lld\n",ans);
    return 0;
}

H.Werewolf
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
Generally, ACMers play Werewolf game anywhere when they go out for any programming contests. There are several roles in this game, including werewolves, villagers, seer, witch, hunter, cupid……

Here is the rule of the game:

The werewolves Each night the werewolves kill a player.

The villagers The villagers has no skills.

The seer Each night the seer can look at a card of a player of his choice to find out the real.

The hunter If the hunter gets killed, the hunter has the power to retaliate by killing a player of his choice immediately.

The cupid On the first night, cupid picks 2 players who he denotes as lovers. Those 2 players will fall madly in love with each another. If one of the lover dies, the other, out of sadness, dies immediately.

The witch The witch knows how to make up 2 extremely powerful potions. One healing potion, which can revive the player that has been killed by the werewolves. One poison potion, which when used at night can kill a player. The witch must use each potion only once during the game.

After each night, everyone wakes up, the god(game master) shows all players which player was killed during the night. After discussion, each player must select one player that they want to eliminate when they vote.

Generally, the werewolves do not select their teammates, but other roles do select anyone when voting. Here comes the problem. How many werewolves at most under the given voting case.

Input

The first line of input file consists of an integer nn(2\le n\le 5000002≤n≤500000), the number of players.

The second line of input file consists of nn integers, and the ii-th number x_ix
​i
​​ (1\le x_i\le n, x_i \ne i1≤x
​i
​​ ≤n,x
​i
​​ ≠i) represents the number of the player selected by the i-th player.

Output

The output file should consist of only one integer, the maximum number of the existed werewolves.

Examples

Input 1

3
2 3 2
Output 1

2
代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
vector<pair<int, int>> v[500001];
int dp[500001][2];
bool used[500001], used2[500001];
int n, s, t;
bool dfs(int i)
{
    used[i] = true;
    for (unsigned int j = 0; j < v[i].size(); j++){
        int k = v[i][j].first, id = v[i][j].second;
        if (!used2[id]){
            if (used[k]){
                v[i].erase(v[i].begin() + j);
                v[k].erase(find(v[k].begin(), v[k].end(), make_pair(i, id)));
                s = i; t = k;
                return true;
            }
            used2[id] = true;
            if (dfs(k))return true;
        }
    }
    return false;
}
void dfs2(int i, int fa)
{
    used[i] = true;
    dp[i][0] = 0; dp[i][1] = 1;
    for (unsigned int j = 0; j < v[i].size(); j++){
        int k = v[i][j].first;
        if (k != fa){
            dfs2(k, i);
            dp[i][0] += max(dp[k][0], dp[k][1]);
            dp[i][1] += dp[k][0];
        }
    }
}
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++){
        int t;
        scanf("%d", &t);
        v[i].push_back(make_pair(t, i));
        v[t].push_back(make_pair(i, i));
    }
    int ans = 0, t1, t2;
    for (int i = 1; i <= n; i++){
        if (!used[i]){
            dfs(i);
            dfs2(s, 0); t1 = dp[s][0];
            dfs2(t, 0); t2 = dp[t][0];
            ans += max(t1, t2);
        }
    }
    printf("%d", ans);
}

注:以上代码纯为粘贴复制大佬的。
个人总结:
期待已久的组队赛在经历了十场左右的个人赛开始了,恰好武汉大学组织了校赛,就作为我们的第一场组队赛。
心里还是激动的,前半场的时候灰常有激情,A题被队友水过,G题(求逆序数)一开始我打了树状数组,TLE,
忽然发现离散化sort会超时,然后就一直GG,最后从模板上找了一个归并排序求逆序数的模板,打了一下,过了。
中场开始有点慌乱,再加上我性子比较急,就开始分析为什么会这样,分析了半天,发现我和我队友都不是会出
思路的人,本人只是代码能力相对较强,思维并不是多好。然后后场一名队友离场,我们俩继续搞,最后就崩盘了。
弱弱的想一句,组队也不容易啊。。。
然后就是感觉之前的好题都没来得及补过,然后这次碰到了,还是一脸懵逼。(好可惜)。
这次比赛让我明白了自己接下来的路该怎么走。真心感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值