Open judge C16H:Magical Balls 快速幂+逆元

C16H:Magical Balls

总时间限制: 
1000ms
 
内存限制: 
262144kB
描述

Wenwen has a magical ball. When put on an infinite plane, it will keep duplicating itself forever.

Initially, Wenwen puts the ball on the location (x0, y0) of the plane. Then the ball starts to duplicate itself right away. For every unit of time, each existing ball on the plane will duplicate itself, and the new balls will be put on the adjacent locations. The duplication rule of these balls is, during the i-th unit of time, a ball, which locates at (x, y), will duplicate uballs to (x, y+1), dballs to (x, y-1), lballs to (x-1, y) and rballs to (x+1, y).

The duplication rule has a period of M. In another words, ui=ui-M, di=di-M, li=li-M, ri=ri-M, for i=M+1,M+2,...

Wenwen is very happy because she will get many balls. It is easy to calculate how many balls she will get after N units of time. However, she wants to know the sum of x-coordinates and y-coordinates of all balls after N units of time. This is a bit difficult for her. Could you help her? Since the sum might be very large, you should give the sum modulo 1,000,000,007 to her.

输入
The first line contains an integer T (1 ≤ T ≤ 25), indicating the number of test cases.

For each test case:

The first line contains four integers N (1 ≤ N ≤ 10^18), M (1 ≤ M ≤ 20,000), x0 and y0 (-10^18 ≤ x0,y0 ≤ 10^18);

Then follows M lines, the i-th line contains four integers: ui, di, li and ri (0 ≤ ui,di,li,ri ≤ 10,000).
输出
For each test case, output one integer on a single line, indicating the sum of x-coordinates and y-coordinates of all balls after N units of time, modulo 1,000,000,007.
样例输入
1
2 2 1 1
2 0 0 0
0 0 0 1
样例输出
19
提示
In the Sample Input:

Initially, there is 1 ball on (1,1).

After 1 unit of time, there is 1 ball on (1,1) and 2 balls on (1,2);

After 2 units of time, there is 1 ball on (1,1), 2 balls on (1,2), 1 ball on (2,1) and 2 balls on (2,2).
Therefore, after 2 units of time, the sum of x-coordinates and y-coordinates of all balls is
(1+1)*1+(1+2)*2+(2+1)*1+(2+2)*2=19.
题意
  给你一个球 初始位置在x0,y0
  和一个周期函数
  这个周期是m天  每天向上复制Ui个球 向下复制Di个球 向左复制Li个球,向右复制Ri个球
  问你n天后 所有球的横纵坐标相加总和是多少
题解
  Si表示第i天答案的总和, sumi 表示第i天球的总和
  S0为初始位置的答案即x+y
  设定ai = ui+ri+li+di+1 , bi = ui+ri-li-di;
  很容易得出
    Si = S0 *  (∏ai)+ ∑j ((∏ai)* bj / a[j]) ; 
  分别用逆元快速幂求解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int N = 2e5+20, M = 1e2+10, MOD = 1e9+7, inf = 2e9;
typedef long long ll;


ll update(ll x) {
     return  ((x % MOD)+MOD)%MOD;
}


ll quick_pow(ll x,ll p) {
    if(!p) return 1;
    ll ans = quick_pow(x,p>>1);
    ans = ans*ans%MOD;
    if(p & 1) ans = ans*x%MOD;
    return ans;
}

ll inv(ll x,ll mo)
{
    return quick_pow(x,mo-2);
}

int T;
ll n;
ll m;
ll U[N],D[N],R[N],L[N],A[N],B[N],Y[N];
int main()
{
    scanf("%d",&T);
    while(T--) {
        ll x,y;
        scanf("%lld%lld%lld%lld",&n,&m,&x,&y);
        ll S0 = (x+y )%MOD;
        ll allA = 1;
        for(int i=1;i<=m;i++) {
            scanf("%lld%lld%lld%lld",&U[i],&D[i],&L[i],&R[i]);
            A[i] = (U[i] + R[i] + L[i] + D[i] + 1 ) % MOD;
            B[i] = (U[i] + R[i] - L[i] - D[i]) % MOD;
            allA = allA * A[i] % MOD;
        }

        ll W = 0;
        for(int i=1;i<=m;i++) W =  (W + B[i] * inv(A[i],MOD) ) % MOD;
        //cout<<W<<endl;
        ll ans = S0 * update(quick_pow(allA, n / m)) % MOD +  update(n/m) * W % MOD * quick_pow(allA, n/m)% MOD;
        ans %= MOD;
        ll sum = quick_pow(allA,n/m);
        //cout<<ans<<" "<<sum<<endl;
        for(int i=1;i<=n%m;i++) {
            ans = (ans * (A[i]) % MOD + sum * B[i] % MOD) % MOD;
            sum = sum * (A[i]) % MOD;
        }
        printf("%lld
",(ans+MOD )%MOD);

    }
    return 0;
}
原文地址:https://www.cnblogs.com/zxhl/p/5682667.html