UVALive - 7715 Guessing Game
2017-07-31 20:11
411 查看
点击打开题目
题意:给出A1,A2,B1,B2,C1,C2,N,问有多少种方法使得A1<=A<=A2,B1<=B<=B2,C1<=C<=C2且A+B+C=N
分析:要使A+B+C = N,即求A+B = N-C有多少种解法,那么N-C有一个取值范围[l, r],且这个区间的一个值唯一对应一个C值,那么现在就是求A+B = K(K = N-C)有多少种取值了
先看这样一个例子, A1 = 0, A2 = 2,B1 = 1, B2 = 6的情况,对于[A1, A2]每个值加上B的值的情况如下
A=0 A=1 A=2 对应的和 对应的和的AB的取法
8 8 1
7 7 7 2
6 6 6 6 3
5 5 5 5 3
4 4 4 4 3
3 3 3 3 3
2 2 2 2
1 1 1
可以发现,在[A1+B1,A2+B1)之间,对应的和的取法为等差数列,且公差为1,在[A2+B1, A1+B2]之间,对应的和的取法不变,在(A1+B2,A2+B2]之间,对应的和的取法为等差数列,公差为-1,暴力枚举各个区间就可以了...
注意: 如果数据量比较小, 用FFT求解会更简便.
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 3e3 + 10;
const ll mod = 1e9 + 7;
using namespace std;
ll qmod(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int T, kase = 1;
ll A1, A2, B1, B2, C1, C2, N;
int main() {
scanf("%d", &T);
while(T--) {
scanf("%lld %lld %lld %lld", &A1, &A2, &B1, &B2);
scanf("%lld %lld %lld", &C1, &C2, &N);
if(B2 - B1 < A2 - A1) { swap(A1, B1); swap(A2, B2); }
ll L1 = A1 + B1, L2 = A2 + B1;
ll L3 = B2 + A1, L4 = A2 + B2;
ll L = N - C2, R = N - C1;
ll ans = 0;
ll a1 = ((L2 - L1) * (L2 - L1 + 1) % mod) * qmod(2, mod - 2) % mod;
ll a2 = (L3 - L2 + 1) * (A2 - A1 + 1) % mod;
ll a3 = a1;
if(L > L4 || R < L1) ans = 0;
else if(L < L1) {
if(R >= L1 && R < L2) {
ans = ((R - L1 + 1) * (R - L1 + 2) % mod) * qmod(2, mod - 2) % mod;
} else if(R >= L2 && R <= L3) {
ans = a1 % mod;
ans = (ans + (R - L2 + 1) * (A2 - A1 + 1) % mod) % mod;
} else if(R > L3 && R <= L4) {
ans = (a1 + a2) % mod;
ans = ((ans + a3 - ((L4 - R) * (L4 - R + 1)) % mod * qmod(2, mod - 2)) + mod) % mod;
} else {
ans = (a1 + a2 + a3) % mod;
}
} else if(L >= L1 && L < L2) {
if(R < L2) {
ll aa1 = (L - L1 + 1) % mod;
ll n = (R - L + 1) % mod;
ans = (n * aa1 + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
} else if(R >= L2 && R <= L3) {
ll aa1 = (L - L1 + 1) % mod;
ll n = (L2 - L) % mod;
ans = (n * aa1 + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
ans = (ans + (R - L2 + 1) * (A2 - A1 + 1) % mod) % mod;
} else if(R > L3 && R <= L4) {
ll aa1 = (L - L1 + 1) % mod;
ll n = (L2 - L) % mod;
ans = (n * aa1 + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
ans = (ans + a2) % mod;
ans = ((ans + a3 - ((L4 - R) * (L4 - R + 1) % mod * qmod(2, mod - 2))% mod ) % mod + mod ) % mod;
} else {
ll aa1 = (L - L1 + 1) % mod;
ll n = (L2 - L) % mod;
ans = (n * aa1 % mod + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
ans = (ans + a2) % mod;
ans =(ans + a3) % mod;
}
} else if(L >= L2 && L <= L3) {
if( R <= L3) {
ans = (R - L + 1) * (A2 - A1 + 1) % mod;
} else if(R > L3 && R <= L4) {
ans = (L3 - L + 1) * (A2 - A1 + 1) % mod;
ans = (ans + a3 - ((L4 - R) * (L4 - R + 1) % mod) * qmod(2, mod - 2) + mod) % mod;
} else {
ans = (L3 - L + 1) * (A2 - A1 + 1) % mod;
ans = (ans + a3) % mod;
}
} else if(L > L3 && L <= L4){
if(R <= L4) {
ll aa1 = (L4 - R + 1) % mod;
ll n = (R - L + 1) % mod;
ans = (n * aa1 % mod + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
} else {
ans = ((L4 - L + 2) * (L4 - L + 1) % mod) * qmod(2, mod - 2) % mod;
}
}
printf("Case #%d: %lld\n", kase++, ((ans % mod) + mod) % mod);
}
return 0;
}
题意:给出A1,A2,B1,B2,C1,C2,N,问有多少种方法使得A1<=A<=A2,B1<=B<=B2,C1<=C<=C2且A+B+C=N
分析:要使A+B+C = N,即求A+B = N-C有多少种解法,那么N-C有一个取值范围[l, r],且这个区间的一个值唯一对应一个C值,那么现在就是求A+B = K(K = N-C)有多少种取值了
先看这样一个例子, A1 = 0, A2 = 2,B1 = 1, B2 = 6的情况,对于[A1, A2]每个值加上B的值的情况如下
A=0 A=1 A=2 对应的和 对应的和的AB的取法
8 8 1
7 7 7 2
6 6 6 6 3
5 5 5 5 3
4 4 4 4 3
3 3 3 3 3
2 2 2 2
1 1 1
可以发现,在[A1+B1,A2+B1)之间,对应的和的取法为等差数列,且公差为1,在[A2+B1, A1+B2]之间,对应的和的取法不变,在(A1+B2,A2+B2]之间,对应的和的取法为等差数列,公差为-1,暴力枚举各个区间就可以了...
注意: 如果数据量比较小, 用FFT求解会更简便.
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 3e3 + 10;
const ll mod = 1e9 + 7;
using namespace std;
ll qmod(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int T, kase = 1;
ll A1, A2, B1, B2, C1, C2, N;
int main() {
scanf("%d", &T);
while(T--) {
scanf("%lld %lld %lld %lld", &A1, &A2, &B1, &B2);
scanf("%lld %lld %lld", &C1, &C2, &N);
if(B2 - B1 < A2 - A1) { swap(A1, B1); swap(A2, B2); }
ll L1 = A1 + B1, L2 = A2 + B1;
ll L3 = B2 + A1, L4 = A2 + B2;
ll L = N - C2, R = N - C1;
ll ans = 0;
ll a1 = ((L2 - L1) * (L2 - L1 + 1) % mod) * qmod(2, mod - 2) % mod;
ll a2 = (L3 - L2 + 1) * (A2 - A1 + 1) % mod;
ll a3 = a1;
if(L > L4 || R < L1) ans = 0;
else if(L < L1) {
if(R >= L1 && R < L2) {
ans = ((R - L1 + 1) * (R - L1 + 2) % mod) * qmod(2, mod - 2) % mod;
} else if(R >= L2 && R <= L3) {
ans = a1 % mod;
ans = (ans + (R - L2 + 1) * (A2 - A1 + 1) % mod) % mod;
} else if(R > L3 && R <= L4) {
ans = (a1 + a2) % mod;
ans = ((ans + a3 - ((L4 - R) * (L4 - R + 1)) % mod * qmod(2, mod - 2)) + mod) % mod;
} else {
ans = (a1 + a2 + a3) % mod;
}
} else if(L >= L1 && L < L2) {
if(R < L2) {
ll aa1 = (L - L1 + 1) % mod;
ll n = (R - L + 1) % mod;
ans = (n * aa1 + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
} else if(R >= L2 && R <= L3) {
ll aa1 = (L - L1 + 1) % mod;
ll n = (L2 - L) % mod;
ans = (n * aa1 + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
ans = (ans + (R - L2 + 1) * (A2 - A1 + 1) % mod) % mod;
} else if(R > L3 && R <= L4) {
ll aa1 = (L - L1 + 1) % mod;
ll n = (L2 - L) % mod;
ans = (n * aa1 + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
ans = (ans + a2) % mod;
ans = ((ans + a3 - ((L4 - R) * (L4 - R + 1) % mod * qmod(2, mod - 2))% mod ) % mod + mod ) % mod;
} else {
ll aa1 = (L - L1 + 1) % mod;
ll n = (L2 - L) % mod;
ans = (n * aa1 % mod + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
ans = (ans + a2) % mod;
ans =(ans + a3) % mod;
}
} else if(L >= L2 && L <= L3) {
if( R <= L3) {
ans = (R - L + 1) * (A2 - A1 + 1) % mod;
} else if(R > L3 && R <= L4) {
ans = (L3 - L + 1) * (A2 - A1 + 1) % mod;
ans = (ans + a3 - ((L4 - R) * (L4 - R + 1) % mod) * qmod(2, mod - 2) + mod) % mod;
} else {
ans = (L3 - L + 1) * (A2 - A1 + 1) % mod;
ans = (ans + a3) % mod;
}
} else if(L > L3 && L <= L4){
if(R <= L4) {
ll aa1 = (L4 - R + 1) % mod;
ll n = (R - L + 1) % mod;
ans = (n * aa1 % mod + (n * (n - 1) % mod) * qmod(2, mod - 2)) % mod;
} else {
ans = ((L4 - L + 2) * (L4 - L + 1) % mod) * qmod(2, mod - 2) % mod;
}
}
printf("Case #%d: %lld\n", kase++, ((ans % mod) + mod) % mod);
}
return 0;
}
相关文章推荐
- UVALive - 7715 The 2016 ACM-ICPC Asia Jakarta Regional Contest E - Guessing Game 繁琐的等差数列求和
- UVALive-7278 - Game of Cards【博弈】【sg定理】
- UVALive 7003 A Balance Game on Trees(树形dp)
- UVALive - 4979 Game 暴力|模拟|签到
- UVALive 4260 Fortune Card Game (Regionals 2008 Asia Taipei +DP)
- UVALive-7278 - Game of Cards
- UVALive 6322 The Swapping Game
- UVALive 6693 - Flow Game(点在线段上判断)
- City Game UVALive - 3029(扫描法)
- UVALive-7278 - Game of Cards(sg函数)
- 例题1.22 最大子矩阵 City Game UVALive - 3029 扫描法
- UVA 1063|11318|UVALive 3807|Marble Game|搜索
- UVAlive 5027 card game KM
- UVa 10530 - Guessing Game
- uva 1521 - GCD Guessing Game(贪心)
- UVALive - 4260 Fortune Card Game (DP&状态转移)好题
- BZOJ 1443 [JSOI2009]游戏Game | UVALive 5882 Racing Car Trail
- UVA 题目1521 GCD Guessing Game(数论+贪心)
- The Same Game UVA 758/Uvalive 5423 大模拟 求最大联通块并清除
- Kejin Game UVALive - 7264 拆点+最小割