题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4790
题意: 给出a,b,c,d,p,m;
在区间[a,b]之间随机选择出x,在区间[c,d]之间随机选择出y,求出现(x+y)%p==m的概率。答案用分数表现出来。
分析: 做完后神奇的发现其他人的方法跟我有些 ,, 很大的差别。貌似别人直接推的规律…
我的方法是 就
既然是分数 ,总方案数 就是分母 肯定是 (b-a+1)*(d-c+1) 接下来求满足要求的x和y
初步想法是
把区间的每个数 都mod p,就可以知道 区间内 取模出来得到结果一样的数每种有多少。
然后对于第一个区间的每一个数x,求出第二个区间的y的个数让(x+y)%p==m
这个处理后每个数都是< p的。
但是这样p还是很大,所以我就把相同的一些数放在一个区间内处理,最后就是对于每个小区间求出对应的对面区间的 次数。
举个例子吧,比如对于区间[4,35] ,p=10。
我处理出来的区间就是[4,9]有1个,[0,9]有2个,[0,5]有1个
然后我的小区间就是 [0,4] ,[4,5], [5,9]. 对于每个区间[L,R],如果有区间 [Li,Ri] 满足Li<=L<=R<=Ri,那么这个区间的数量就可以被加进去,然后就是各种细节处理。 对应所在的另一个区间是[p+m-R,p+m-L]。
大致想法就这样。
接下来是代码,随便看看。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct qujian
{
ll L,R,num;
} e[5],f[5];
void add(qujian q[],ll a,ll b,ll c,ll &pos)
{
q[pos++]=(qujian)
{
a,b,c
};
}
ll work(ll L,ll R,qujian q[],ll pos)
{
if(L>R) return 0;
ll te=0;
for(ll i=0; i<pos; i++)
{
if(q[i].L<=L&&q[i].R>=R)
te+=q[i].num;
}
return te;
}
int main()
{
// freopen("1.in","r",stdin);
// freopen("2.out","w",stdout);
int T,cas=1;
scanf("%d",&T);
while(T--)
{
set<ll>s;
ll hx=0,hx1=0;
ll a,b,c,d,p,m;
cin>>a>>b>>c>>d>>p>>m;
printf("Case #%d: ",cas++);
if(p==1)
{
printf("1/1\n");
continue;
}
ll fz=0,fm;
fm=b-a+1;
fm*=d-c+1;
ll aa=a%p;
ll bb=b%p;
s.insert(0);
if(aa)
{
a-=aa;
add(e,0,aa-1,-1,hx);
s.insert(aa-1);
s.insert((p+m-aa+1)%p);
}
b-=bb;
if(bb)
add(e,1,bb,1,hx),s.insert(bb),s.insert((p+m-bb)%p),s.insert(1),s.insert((p+m-1)%p);
add(e,0,p-1,(b-a)/p,hx);
add(e,0,0,1,hx);
s.insert(p-1);
a=c;
b=d;
aa=a%p;
bb=b%p;
if(aa)
{
a-=aa;
add(f,0,aa-1,-1,hx1);
s.insert(aa-1);
s.insert((p+m-aa+1)%p);
}
b-=bb;
if(bb)
add(f,1,bb,1,hx1),s.insert(bb),s.insert((p+m-bb)%p),s.insert(1),s.insert((p+m-1)%p);
add(f,0,p-1,(b-a)/p,hx1);
add(f,0,0,1,hx1);
set<ll>::iterator it=s.begin();
it++;
ll pre=0;
fz+=work(0,0,e,hx)*work(m,m,f,hx1);
for(; it!=s.end(); it++)
{
ll id=*it;
ll te=0,te1=0;
id--;
ll L=pre+1,R=id;//[L,R]是小区间
if(L>R)
goto TAR;
if(L>m)
{
ll len=R-L+1;
fz+=work(L,R,e,hx)*work(p+m-R,p+m-L,f,hx1)*len;
}
else if(R<m)
{
ll len=R-L+1;
fz+=work(L,R,e,hx)*work(m-R,m-L,f,hx1)*len;
}
else
{
fz+=work(L,m-1,e,hx)*work(1,m-L,f,hx1)*(m-L);
fz+=work(m,m,e,hx)*work(0,0,f,hx1);
if(m<R)
fz+=work(m+1,R,e,hx)*work(p+m-R-1,p-1,f,hx1)*(R-m);
}
TAR:
id++;
fz+=work(id,id,e,hx)*work((p+m-(id))%p,(p+m-(id))%p,f,hx1);
pre=id;
}
if(fz==0)
fm=1;
else
{
ll g=__gcd(fz,fm);
fz/=g;
fm/=g;
}
printf("%I64d/%I64d\n",fz,fm);
}
}