#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll prime[100], times[200], value[200];
ll fac[120500];
ll p, n, m;
ll thingsamount[100];
int divide(ll n)
{
int tot = 0;
for (ll i = 2; i*i <= n; i++)
{
if (n%i == 0)
{
prime[tot] = i; times[tot] = 1; value[tot] = i; n /= i;
while (n%i == 0)value[tot] *= i, times[tot]++, n /= i;
tot++;
}
}
if (n > 1)prime[tot] = n, value[tot] = n, times[tot] = 1,tot++;
return tot;
}
ll pow(ll prime, ll times, ll mod)
{
ll value = 1; ll temp = prime;
while (times)
{
if (times & 1)value *= temp,value%=mod;
temp *= temp; times >>= 1;
temp %= mod;
}
return value;
}
ll rev(ll a, ll mod,ll prime)
{
ll ruler = (mod / prime)*(prime - 1);
return pow(a, ruler-1, mod);
}
ll cal(ll n, ll prime, ll t, ll value, ll &e,ll euler)
{
if (n < prime)
{
e = 0;
return fac[n];
}
ll res = cal(n / prime, prime, t, value, e,euler);
e += n / prime; n -= n / prime;
ll anotherres = n%euler; anotherres = fac[anotherres];
bool ischange = (n / euler) % 2;//为什么2会比较特殊?因为x mod m=a1 推出x mod m1=a1但是x mod m1=a1退不出x mod m=a1因为有可能解很多
if (ischange && (prime != 2 || (prime == 2 && t < 3)))
anotherres = value -anotherres;
return (anotherres*res) % value;
}
ll gcd(ll a, ll b)
{
if (b == 0)return a;
gcd(b, a%b);
}
ll solve(ll prime, ll t, ll value)
{
ll ans1,ans2=1,e1,e2=0,tempe;
ll euler = value / prime*(prime - 1);
int tot = 1; fac[1] = 1; fac[0] = 1;
for (int i = 2; tot < euler; i++)
if (gcd(i, value) == 1)
fac[++tot] = (fac[tot - 1] * i) % value;
ans1 = cal(thingsamount[0], prime, t, value, e1,euler);
for (int i = 1; i <= m + 1; i++)
ans2 *= cal(thingsamount[i], prime,t, value, tempe, euler),e2+=tempe,ans2%=value;
ll ans3 = pow(prime, e1 - e2, value);
ans2 = pow(ans2, euler - 1, value);
return ((ans2*ans1) % value*ans3) % value;
}
int main()
{
scanf("%lld%lld%lld", &p, &n, &m);
thingsamount[0] = n; int allr = 0;
for (int i = 1; i <= m; i++)
scanf("%lld", &thingsamount[i]),allr+=thingsamount[i];
allr = n - allr;
if (allr < 0)
{
printf("Impossible\n");
return 0;
}
thingsamount[m + 1] = allr;
int all = divide(p);
ll ans = 0;
for (int i = 0; i < all; i++)
{
ll M = p / value[i];
ll temp = solve(prime[i], times[i], value[i]);
ans += (((temp*M) % p)*(rev(M, value[i], prime[i])%p))%p;
}
printf("%lld\n", ans%p);
return 0;
}
此题两个地方易错 一是thingsamount[m+1] 2是全都要去摸啊!!!
bzoj2142礼物
最新推荐文章于 2019-08-16 14:50:53 发布