HRY and Abbas

原题

HRY and Abbas

Problem Description

In a parallel universe, HRY is the president of the Kassel Academy Student Union. Once he and the Lionheart Association President Abdullah Abbas performed a secret mission: to investigate the mixed blood drug trafficking group in country X.
However, an accident happened and they were caught together. They were forced to play Russian gambling roulette games!
The terrorists brought a revolver which works as follows: a revolver has n places 1,2,…,n to place bullet, and these n places forms a circle. The revolver has a position it is currently pointing at, and when pulling the trigger, the revolver will shoot out the bullet (if it has) at the current position and turn to the next position. The next position of 1 ≤ i ≤ n-1 is n+1, and for n the next position is 1. Now the terrorist puts m bullets in the revolver, and turned the wheel of the revolver, which means the starting position is randomly chosen. He orders HRY and Abbas shoot at their heads in turn using the same revolver. If someone is hit by bullet, then the game is over.
HRY and Abbas are both not ordinary mixed blood, so the revolver can do no harm to them. However, they still decided to play the game. Now they want to know the probability of the game ending exactly after the ith shoot.

input

The first line is an integer T, indicating the number of test cases.
For each test case there are two lines :
The first line contains two integers n,m, and the second line contains m different positive integers ai, indicating the initial positions of bullets.
1 ≤ T ≤ 1000, 1 ≤ m ≤ n ≤ 105, 1 ≤ ai ≤ n
The sum of n does not exceed 106

ouput

For each test case output n lines, the ith line indicates the probability of game ending exactly after the ith shoot. The probability is in the form of irreducible fraction p/q, which means the greatest common divisor of p and q is 1. If the answer is 0, output 0 directly.

Sample Input

2
10 2
1 3
10 4
1 2 6 10

Sample Output

1/5
1/5
1/10
1/10
1/10
1/10
1/10
1/10
0
0
2/5
1/5
1/5
1/5
0
0
0
0
0
0

题意分析:

题目的意思是,有一把类似于左轮的枪(弹夹是环形的),最多有n个位置(位置编号从1开始)可以装子弹,其中有m个位置是有子弹的,其余位置是没有子弹的,现在随机选一个位置开始,不断地让大家轮流开枪,直到第一个人死亡时,游戏结束。输入第一行是样例个数,以下一行是n m,接下来是m个数,代表m个有子弹的位置。要求输出n行,分别表示第一枪就结束游戏的概率,第二枪结束的概率。。。第n枪结束的概率。
ps:当概率为1时,输出1/1

总体思路:

仔细分析,问题其实十分简单。
现在用第一个样例输入说明思路:
现在有子弹的分布如下图所示:(第一行代表位置标号,第二行代表弹夹,黄色代表有子弹,绿色无子弹)
在这里插入图片描述
首先我们定义一个数组a,数组表示从第i个位置开始,要打多少枪结束游戏。
观察上图,我们发现,从第一个位置开始只要打一枪就结束游戏;从第二个位置开始要经历第2,3个位置结束游戏;从第三个位置开始则打一枪就结束游戏;从第四个位置开始则要经历4,5,6,7,8,9,10,1一共8枪才结束游戏。。。
因此我们的数组a就确认了。

数组a

数组a

最后我们再定义一个数组cnt,用来统计第一枪结束的情况个数,第二枪结束的情况个数。。。。第n枪结束的情况个数。最后,根据a数组,可以导出cnt数组。

数组cnt

数组cnt到此,答案已经出来了,即分别将cnt数组每一项除以n输出后就是答案。
仔细想想,到这里其实还有一个小问题,就是如何快速确认我们的a数组,如何可以快速知道从当前位置开始要打多少枪结束游戏?其实我们可以建立一个next数组,记录离第i个位置最近的右边(因为可以循环,所以并不是严格的右边,而是逻辑的右边)的位置,这样就可以轻松算出当前位置需要打多少枪结束。

数组next

在这里插入图片描述

AC代码:

ps:题目没有说给出的m个位置是有序的,因此在建立next数组时,要先sort。

#include <iostream>
#include <algorithm>
#include <cstdio>
#define MAXN 100005
using namespace std;
typedef long long ll;
int Next[MAXN] = {0};
ll cnt[MAXN] = {0};
int n, m;
int f(int a, int b){
   if (a > b){
       return b+n-a+1;
   }else{
       return b-a+1;
   }  
}
ll gcd (ll x, ll y){
   return y == 0 ? x : gcd(y, x%y);
}
void output(ll a, ll b){
   if (a == 0){
       printf("0\n");
       return ;   
   }
   ll g = gcd(a, b);
   a /= g;
   b /= g;
   printf("%lld/%lld\n", a, b);
}
int main(){
   int i, j, x, T;
   scanf ("%d", &T);
   while (T--){
       for (i = 0; i < MAXN; i++){
           Next[i] = cnt[i] = 0;
       }
       scanf ("%d%d", &n, &m);
       ll temp[MAXN] = {0};
       for (j = 0; j < m; j++){
           scanf ("%d", &x);
           temp[j] = x;
       }
       sort(temp, temp+m);
       if (m == 1){
           for (i = 1; i <= n; i++){
               output(1, n);
           }
           continue;
       }else{
           for (j = 0; j < m; j++){
               ll left = temp[j], right = temp[(j+1)%m];
               ll len = f(left, right);
               Next[left] = left;
               Next[right] = right;
               for (i = 0; i < len-2; i++){
                   if (!Next[(i+left)%n+1]){
                       Next[(i+left)%n+1] = right;
                   }
               }
           }
       }

       for (i = 1; i <= n; i++){
           cnt[f(i, Next[i])]++;
       }
       ll sum = 0;
       for (i = 1; i <= n; i++){
           sum += cnt[i];
       }
       for (i = 1; i <= n; i++){
           output(cnt[i], sum);
       }
   }
   return 0;
}
变分模态分解(Variational Mode Decomposition, VMD)是一种强大的非线性、无参数信号处理技术,专门用于复杂非平稳信号的分析与分解。它由Eckart Dietz和Herbert Krim于2011年提出,主要针对传统傅立叶变换在处理非平稳信号时的不足。VMD的核心思想是将复杂信号分解为一系列模态函数(即固有模态函数,IMFs),每个IMF具有独特的频率成分和局部特性。这一过程与小波分析或经验模态分解(EMD)类似,但VMD通过变分优化框架显著提升了分解的稳定性和准确性。 在MATLAB环境中实现VMD,可以帮助我们更好地理解和应用这一技术。其核心算法主要包括以下步骤:首先进行初始化,设定模态数并为每个模态分配初始频率估计;接着采用交替最小二乘法,通过交替最小化残差平方和以及模态频率的离散时间傅立叶变换(DTFT)约束,更新每个模态函数和中心频率;最后通过迭代优化,在每次迭代中优化所有IMF的幅度和相位,直至满足停止条件(如达到预设迭代次数或残差平方和小于阈值)。 MATLAB中的VMD实现通常包括以下部分:数据预处理,如对原始信号进行归一化或去除直流偏置,以简化后续处理;定义VMD结构,设置模态数、迭代次数和约束参数等;VMD算法主体,包含初始化、交替最小二乘法和迭代优化过程;以及后处理,对分解结果进行评估和可视化,例如计算每个模态的频谱特性,绘制IMF的时频分布图。如果提供了一个包含VMD算法的压缩包文件,其中的“VMD”可能是MATLAB代码文件或完整的项目文件夹,可能包含主程序、函数库、示例数据和结果可视化脚本。通过运行这些代码,可以直观地看到VMD如何将复杂信号分解为独立模态,并理解每个模态的物理意义。 VMD在多个领域具有广泛的应用,包括信号处理(如声学、振动、生物医学信号分析)、图像处理(如图像去噪、特征提取)、金融时间序列分析(识
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值