NKOJ 费马小定理降幂 P3511无聊的计算

无聊的计算
【问题描述】
nodgd 经常遇到很无聊的计算题,你看,这次又遇到了……
这个题一开始给了 nodgd 两个序列𝑎1, 𝑎2, … , 𝑎𝑛, 𝑏1, 𝑏2, … , 𝑏𝑚。定义一个二
元函数𝑓(𝑢, 𝑝) = 𝑣,其中0 ≤ 𝑣 < 𝑝,且存在整数𝑘使得𝑢 = 𝑣 + 𝑘𝑘。现在,这道
题要计算满足条件𝑓 �𝑎𝑖
𝑏𝑗, 𝑝� ≤ 𝑞的有序数对(𝑖,𝑗)有多少个。
【输入格式】
输入文件 A.in。
第一行两个整数𝑝, 𝑞。
第二行六个数𝑛, 𝑎1, 𝑎2, 𝐴, 𝐵, 𝐶,当𝑖 ≥ 3时,𝑎𝑖 = 𝐴 × 𝑎𝑖−1 − 𝐵 × 𝑎𝑖−2 − 𝐶。
第三行六个数𝑚, 𝑏1, 𝑏2,𝐷, 𝐸, 𝐹,当𝑖 ≥ 3时,𝑏𝑖 = 𝐷 × 𝑏𝑖−1 + 𝐸 × 𝑏𝑖−2 + 𝐹。
【输出格式】
输出文件 A.out。
输出一个整数,表示满足条件的(𝑖,𝑗)数量。
【样例输入】
5 3
3 2 2 1 0 4
3 3 2 4 2 1
【样例输出】
6
【样例解释】
根据输入可以算出𝑎3 = −2, 𝑏3 = 15。
满足条件的(𝑖,𝑗)有(1,1), (2,1), (3,1), (1,3), (2,3), (3,3)。
【数据范围】
对于 20%的数据,𝑛, 𝑚 ≤ 6;
对于 40%的数据,𝑛, 𝑚 ≤ 1000;
对于 60%的数据,𝑛, 𝑚 ≤ 5000;
对于 100%的数据,2 ≤ 𝑛, 𝑚 ≤ 106, 5 ≤ 𝑝 ≤ 5000, 0 ≤ 𝑞 ≤ 𝑝 − 1,输入的
所有其他数都非负且不超过 1000,保证p 为质数
 
费马小定理降幂! 
x^(p-1)=1 (mod p) 
 
改一下即可 
 
在𝑚od 𝑝的意义下,𝑎𝑖没有必要用真是的值,用𝑎𝑖′ = 𝑎𝑖 𝑚od 𝑝来
代替𝑎𝑖就可以得到完全一样的效果。这样一来,真正算出来的𝑎𝑖′ 的大小都在0到𝑝 − 1 范围内
 
code:
 
//
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
ll a[3000000],b[3000000];
ll n,m;
ll p,q;
ll sum[80000],tot;
ll sum1[80000],tot1;
ll A,B,C,D,E,F;
ll ksm(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%p;
        b>>=1;
        a=(a*a)%p;
    }
    return ans;
}
int main()
{
    scanf("%lld%lld",&p,&q);
    scanf("%lld%lld%lld%lld%lld%lld",&n,&a[1],&a[2],&A,&B,&C);
    scanf("%lld%lld%lld%lld%lld%lld",&m,&b[1],&b[2],&D,&E,&F);
    sum[(b[1]%(p-1)+(p-1))%(p-1)]++;
    sum[(b[2]%(p-1)+(p-1))%(p-1)]++;
    sum1[(a[1]+p)%p]++;
    sum1[(a[2]+p)%p]++;
    for(int i=3;i<=m;i++)
    {
        b[i]=((D%(p-1))*(b[i-1]%(p-1))+(E%(p-1))*(b[i-2]%(p-1))+F%(p-1))%(p-1);
        sum[(((b[i]%(p-1)+p-1))%(p-1))]++;
    }
    for(int i=3;i<=n;i++)
    {
        a[i]=((A%p)*a[i-1]-(B%p)*a[i-2]-(C%p)+p)%p;
        sum1[(a[i]+p)%p]++;
    }
    ll ans=0;
    for(int i=0;i<=p-1;i++)
        for(int j=0;j<p-1;j++)
        {
            if(sum[j]&&sum1[i])
            if((ksm(i,j))<=q) ans+=(sum[j]*sum1[i]);
        }
    printf("%lld",ans);
}

 

 
posted @ 2019-08-09 00:13  ALEZ  阅读(265)  评论(0编辑  收藏  举报