HDU 4790 找規律
題意是說區間[a,b]取一個數x,[c,d]取一個數y,求(x+y)%p==m的概率
可知,分母是(b-a+1)*(d-c+1),接下來就是找分子的個數了,即一共有多少個滿足性質的整數對(x,y)使得(x+y)%p == m
一、區間減法的性質
可以轉化為求[0,b][0,d]中取整數對(x,y)有多少對
即
[a,b][c,d] = [0,b][0,d] - [0,a-1][0,d] - [0,b][0,d-1] + [0,a-1][0,c-1];
二、求[0,a][0,b]中的整數對滿足(x+y)%p = m
觀察發現 x y
0 m
1 m-1
2 m-2
... ...
m 0 x+y=m
-----------------------華麗麗的小分割線---------
m+1 p-1 x+y=p+m
m+2 p-2
.. ...
p-1 m+1
假設左邊有k1個滿足x%p==0,右邊有k2個滿足y%p==m,那麼對這一行就是k1*k2。但是,但是這種情況下的分類討論似乎很難做
於是繼續拆分[0,a]拆成[0,k1*p-1]和[k1*p,a];[0,b]拆成[0,k2*p-1]和[k2*p,b];
分類討論
1. [0,k1*p-1][0,k2*p-1]
一一對應的關係 p*k1*k2
2.[0,k1*p-1][k2*p,b]
把[k2*p,b]當成[0,b%p],那麼對於每一個y在[0,b%p]都有k1個對應的x 即(b%p+1)*k1
3.[k1*p,a][0,k2*p-1]
同上 (a%p+1)*k2
4.[k1*p,a][k2*p,b]
又要分類了,觀察上面的規律
4.1 a%p>=m b%p>=m m+1+{ m+p-(b%m) <= x <= a%p }
4.2 a%p>=m b%p<m b%p+1
4.3 a%p<m b%p>=m a%p+1
4.4 a%p<m b%p<m {m-b%p <= x <= a%p}
#include <stdio.h>
#include <string.h>
#include <queue>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stdlib.h>
using namespace std;
typedef unsigned long long ll;
const int maxn = 100005;
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
ll solve(int a,int b,int p,int m){
if(a < 0 || b < 0)return 0;
//ll ans = (a/p+a%p)*(b/p+b%p);
// printf("%d %d %d %d\n",a,b,p,m);
int sa = a/p;
int sb = b/p;
int ma = a%p;
int mb = b%p;
ll ans = (ll)p*sa*sb+(ll)sa*(mb+1)+(ll)sb*(ma+1);
//printf("%lld\n",ans);
if(ma >= m && mb >= m){
ans += 1 + m + max(ma-(m+p-mb)+1,0);
}
else if(ma >= m && mb < m){
ans += mb+1;
}
else if(ma < m && mb >= m){
ans += ma+1;
}
else if(ma < m && mb < m){
ans += max(0,ma-(m-mb)+1);
}
//printf("%lld\n",ans);
return ans;
}
//0 0 10 10 3 2
int main(){
int a,b,c,d,p,m;
// freopen("out","r",stdin);
// freopen("out1","w",stdout);
int T;
cin >> T;
//T = 100;
int cas = 1;
while(T --){
cin >> a >> b >> c >> d >> p >> m;
//printf("%d %d %d %d %d %d\n",a,b,c,d,p,m);
ll ansx = solve(b,d,p,m)-solve(a-1,d,p,m)-solve(b,c-1,p,m)+solve(a-1,c-1,p,m);
ll ansy = (ll)(b-a+1)*(d-c+1);
ll _gcd = gcd(ansx,ansy);
printf("Case #%d: ",cas++);
printf("%I64d/%I64d\n",ansx/_gcd,ansy/_gcd);
//cout << ans << endl;
}
}
/*
int main(){
ll cnt = 0;
freopen("out","w",stdout);
cout << 1884960 << endl;
for(int a=0;a<=15;a++){
for(int b=a;b<=15;b++){
for(int c=10;c<=20;c++){
for(int d=c;d<=20;d++){
for(int p=1;p<=20;p++){
for(int m=0;m<p;m++){
//cnt ++;
printf("%d %d %d %d %d %d\n",a,b,c,d,p,m);
}
}
}
}
}
}
//cout << cnt << endl;
}
*/