BZOJ4891 TJOI2017龙舟(Polllard-Rho)

时间:2023-03-09 03:51:08
BZOJ4891 TJOI2017龙舟(Polllard-Rho)

  对给定模数分解质因数后约分即可。依然常数巨大过不了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 10010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
ll gcd(ll n,ll m){return m==?n:gcd(m,n%m);}
ll read()
{
ll x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,q,cnt,p[],prime[],tot[],t;
ll g[],a[][N],b[N],c[N],d[N];
bool flag[];
ll ksc(ll a,ll b,ll p)
{
ll t=a*b-(ll)((long double)a*b/p+0.5)*p;
return t<?t+p:t;
}
ll ksm(ll a,ll k,ll p)
{
ll s=;
for (;k;k>>=,a=ksc(a,a,p)) if (k&) s=ksc(s,a,p);
return s;
}
void exgcd(ll &x,ll &y,ll a,ll b)
{
if (b==)
{
x=,y=;
return;
}
exgcd(x,y,b,a%b);
ll t=x;x=y;y=t-a/b*x;
}
ll inv(ll a,ll p)
{
ll x,y;exgcd(x,y,a,p);
x=(x%p+p)%p;
return x;
}
bool check(int k,ll n)
{
if (ksm(k,n-,n)!=) return ;
ll p=n-;
while (!(p&))
{
p>>=;ll x=ksm(k,p,n);
if (x==n-) return ;
if (x!=) return ;
}
return ;
}
bool Miller_Rabin(ll n)
{
if (n<=) return !flag[n];
return check(,n)&&check(,n)&&check(,n)&&check(,n)&&check(,n)&&check(,n);
}
ll f(ll x,ll p,int c){return (ksc(x,x,p)+c)%p;}
void getfactor(ll n)
{
if (n<=)
{
while (n>) g[++cnt]=p[n],n/=p[n];
return;
}
if (Miller_Rabin(n)) {g[++cnt]=n;return;}
while ()
{
int c=rand()%(n-)+;
ll x=rand()%n,y=x;
do
{
ll z=gcd(abs(x-y),n);
if (z>&&z<n) {getfactor(z),getfactor(n/z);return;}
x=f(x,n,c),y=f(f(y,n,c),n,c);
}while (x!=y);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4891.in","r",stdin);
freopen("bzoj4891.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read(),q=read();
flag[]=;
for (int i=;i<=;i++)
{
if (!flag[i]) prime[++t]=i,p[i]=i;
for (int j=;j<=t&&prime[j]*i<=;j++)
{
flag[prime[j]*i]=;
p[prime[j]*i]=prime[j];
if (i%prime[j]==) break;
}
}
for (int i=;i<=m;i++) b[i]=read();
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
a[i][j]=read();
while (q--)
{
int x=read();ll y=read(),ans=;cnt=;getfactor(y);
sort(g+,g+cnt+);cnt=unique(g+,g+cnt+)-g-;memset(tot,,sizeof(tot));
memcpy(c,b,sizeof(c));memcpy(d,a[x],sizeof(d));
for (int i=;i<=m;i++)
{
for (int j=;j<=cnt;j++)
while (c[i]%g[j]==) tot[j]++,c[i]/=g[j];
for (int j=;j<=cnt;j++)
while (d[i]%g[j]==) tot[j]--,d[i]/=g[j];
ans=ksc(ksc(ans,c[i],y),inv(d[i],y),y);
}
for (int i=;i<=cnt;i++)
if (tot[i]<) {ans=-;break;}
else ans=ksc(ans,ksm(g[i],tot[i],y),y);
cout<<ans<<endl;
}
return ;
}