Codeforces Round 933 (Div. 3) D 题

D. Rudolf and the Ball Game

原题链接:

https://codeforces.com/contest/1941/problem/D 

Rudolf and Bernard decided to play a game with their friends. n people stand in a circle and start throwing a ball to each other. They are numbered from 1 to nn in the clockwise order.

Let's call a transition a movement of the ball from one player to his neighbor. The transition can be made clockwise or counterclockwise.

Let's call the clockwise (counterclockwise) distance from player y1 to player y2 the number of transitions clockwise (counterclockwise) that need to be made to move from player y1 to player y2. For example, if n=7 then the clockwise distance from 2 to 5 is 3, and the counterclockwise distance from 2 to 5 is 4.

Initially, the ball is with the player number x (players are numbered clockwise). On the ii-th move the person with the ball throws it at a distance of riri (1≤ri≤n−1) clockwise or counterclockwise. For example, if there are 7 players, and the 2nd player, after receiving the ball, throws it a distance of 55, then the ball will be caught by either the 7th player (throwing clockwise) or the 4th player (throwing counterclockwise). An illustration of this example is shown below.

 

 

 

The game was interrupted after mm throws due to unexpected rain. When the rain stopped, the guys gathered again to continue. However, no one could remember who had the ball. As it turned out, Bernard remembered the distances for each of the throws and the direction for some of the throws (clockwise or counterclockwise).

Rudolf asks you to help him and based on the information from Bernard, calculate the numbers of the players who could have the ball after m throws.

Input

The first line of the input contains a single integer t (1≤t≤104) — the number of test cases. Then follow the descriptions of the test cases.

The first line of each test case contains three integers n,m,x (2≤n≤1000, 1≤m≤1000, 1≤x≤n) — the number of players, the number of throws made, and the number of the player who threw the ball first, respectively.

The next mm lines contain information about each throw in order. Each of them contains an integer riri (1≤ri≤n−1) — the distance at which the i-th throw was made, and a symbol ci, equal to '0', '1', or '?':

  • if ci='0', then the ii-th throw was made clockwise,
  • if ci='1', then the ii-th throw was made counterclockwise,
  • if ci='?', then Bernard does not remember the direction and the i-th throw could have been made either clockwise or counterclockwise.

It is guaranteed that the sum n⋅m (n multiplied by m) over all test cases does not exceed 2⋅105.

  

Output

For each test case, output two lines.

In the first line, output the number of players k (1≤k≤n) who could have the ball at the end of the game.

In the next line, output kk numbers bi (1≤bi≤n) — the numbers of the players in increasing order. All numbers must be different.

题意:

 n个人围着坐成了一圈,然后开始的时候球位于第x个人手中,然后要进行m次传递,求m次传递后可能拿球的人。传球有顺时针和逆时针两种传球方式,假设第j个人持有球,如果是顺时针,则为(j+r+n)%n ,  如果是逆时针,则为(j-r+n)%n。

解决方案: 

这道题我们使用动态规划来解决,怎么使用呢,一共不是m次投球嘛,我们让dp数组,代表经过m次投球后可能拿到求的人,如果dp[i]为1的话,此人就可能持有球。dp数组需要经过m次更新,每投一次求,就更新一次,即代表投了j次求后的可能持有球的人。
 

代码实现:

#include<bits/stdc++.h>

using i64=long long;

void solve()
{
    int n,m,x;
    std::cin>>n>>m>>x;
    std::vector<int> dp(n);
    x--;
    dp[x]=1;
    for(int i=0;i<m;i++)
    {
        int r;
        char c;
        std::cin>>r>>c;
        std::vector<int> g(n);
        for(int j=0;j<n;j++)
        {
            if(dp[j])
            {
                if(c!='1')
                {
                    g[(j+r)%n]=1;
                }
                if(c!='0')
                {
                    g[(j-r+n)%n]=1;
                }
            }
        }
        dp=g;
    }
    int ans=std::count(dp.begin(),dp.end(),1);//计算dp数组当中有多少个1
    std::cout<<ans<<"\n";
    for(int i=0;i<n;i++)
    {
        if(dp[i])
        {
            std::cout<<i+1<<" ";
        }
    }
    std::cout<<"\n";
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    std::cin>>t;

    while(t--)
    {
        solve();
    }

    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值