Gym - 101864A A Criminal (约瑟夫环 M = 2, + 暴力)
A Criminal
After committing a serious crime ( Killing an innocent mosquito who never bites any animal) you are arrested by ACM’s Defense Team. You are the X-th (1 based index ) criminal in the ordered list of N criminals. Defense Team are willing to punish criminals for their horrible crime. First day Defense Team take first Y people from criminal list and arrange them in a circle ( Just like the picture bellow remember that given picture is valid when Y is equal to 8 )
After forming circle they start from criminal one and simulate clockwise. They skip one person and punish next person from the active list (active list: person who have not been punished yet). When only one person is left in the active list they just do not punish him as he is a special person. The order of punishment when Y = 8 is [2, 4, 6, 8, 3 , 7, 5] 1 will not be punished in that case.
You know that Defense Team will not take less than L from criminal list while making circle and you also know that taking any( in range [L,N] ) number of criminal form list is equally probable.
You are good at programming so you want to calculate the probability that you will not punished on the first day.
INPUT Specification
First line of the input will contain an integer T denoting number of test cases. Next T lines will contain Three Integer X , L , N.
X: Your position on Criminal List .
L: Minimum number of criminal that Defense Team Can take.
N: Total number of criminal on that list.
Constraints
1 ≤ T ≤ 10500
1 ≤ X ≤ N ≤ 10^15
1 ≤ L ≤ N
Output Specification
For every case print case number (See sample output for exact format) and print the answer ( Probability that you will not punished on first day) as p/q format where p and q are coprime If the answer is 0, then you should print 0/1.
Sample Input
3
1 1 1
2 3 10
4 1 7
Sample Output
Case 1: 1/1
Case 2: 0/1
Case 3: 3/7
Explanation
First Case
There is only one option which is taking one person from list. and you will not be punished because remaining person in circle is 1 already(which is actually you). So ans is 1/1.
Second Case
There are 8 equally probable option for Y (3,4,5,6,7,8,9,10). And for each one of those you are going to be punished. So ans is 0/1
Third Case:
This are 7 equally probable options of Y (1,2,3,4,5,6,7). When Y is 1 or 2 or 3 you will not be punished (Actually you are not even selected to be a part of the circle because your id is 4). So ans is 3/7.
题意:题意是给你 三个整数 X ,L ,N. X 表示当前人的 编号, L 表示每一个 惩罚选取的最少人数, N 是总人数。惩罚人数只选取一次,也就是选取 L ~ N中的一个数, 其中每个数被选取的概率都相同。 对于每一次惩罚,相当于约瑟夫环 M = 2 的情况。 求 X 这个人不被惩罚的概率。
思路:很显然,偶数的情况比较简单,所以我是先将偶数的情况特殊处理,然后在来确定奇数。
对于约瑟夫环 M = 2 的情况,有结论 若选取的总人数是 2^k + t, 则最后留下的人的编号是 2*t + 1。
这样,就可以通过 2 * t + 1 这个式子,算出来 X 这个人为最后幸存者 时的 t, 接着枚举 k ,即枚举 2 的次方,算出所有可能的 留下的是 X 时 的总人数。 然后判断 有多少个数 在 max(L,X)~ N 的范围内,就可以算出 X 这个人存活的概率了。 因为是枚举次方, 所以并不会太多, 66次足够了(枚举小了会 WA)。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll pow_t[70];
ll gcd(ll a,ll b){
ll r = a % b;
while(r){
a = b; b = r; r = a % b;
}
return b;
}
int main()
{
pow_t[0] = 1;
for(int i = 1;i <= 66;i ++)
pow_t[i] = pow_t[i-1] * 2;
ll x,l,n;
int cas = 1;
int t; scanf("%d",&t);
while(t --){
scanf("%I64d%I64d%I64d",&x,&l,&n);
printf("Case %d: ",cas ++);
if(n == 1){ printf("1/1\n"); continue; }
if(x % 2 == 0 && x <= l){ printf("0/1\n"); continue; } ///必死
if(x % 2 == 0){ ll g = gcd(x - l,n - l + 1); printf("%I64d/%I64d\n",(x - l) / g,(n - l + 1) / g); continue; } ///被取必死
ll t = (x - 1) / 2;
ll num[70] = {0}, pn = 0;
for(int i = 0;i <= 66;i ++) ///枚举
num[pn ++] = pow_t[i] + t;
int cnt = 0;
for(int i = 0;i < pn;i ++){
if(max(l,x) <= num[i] && num[i] <= n) ///用 max 是判断 X 与 L 的大小关系
cnt ++;
}
ll f = cnt;
if(l <= x) f += x - l;
ll g = gcd(f,n - l + 1);
printf("%I64d/%I64d\n",f / g,(n - l + 1) / g);
}
return 0;
}
上一篇: PHP怎么上传大文件?且带有进度条
下一篇: Nginx开发入门