【BZOJ 1005】[HNOI2008]明明的烦恼(化简的另一种方法)
【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1005
【题意】
【题解】
题目和题解在上一篇;
这里 对
【(m^(n-2-tot))* (n-2)!】/【(n-2-tot)!* (d[1]-1)!*(d[2]-1)!……(d[n]-1)!】;
这个式子的化简再说一个方法;
对于n!
最后分解成质因子的时候;
质因子p的指数应该为
∑(n/i);
这里i为p,p^2,p^3….p^x,且p^x<=n
这样;
因为最大要求的阶乘为(n-2)!
所以先处理出2..n-2之间哪些数是质数;
然后对于x!
直接枚举2..x之间的那些质数;
然后i=p,p平方,p立方,p的4次方..那样加上n/i;
知道某个质数的指数之后,直接根据是分子还是分母,分别加上或减去那个∑(n/i)就好;
这样就不用1..x里面每个数都再去分解一次质因数了;
//直接暴力搞
for (int i = 1;i <= x;i++)
{
int x = i;
for (int j= 2;j*j <= x;j++)
while (x%j==0)
{
cnt[j]->change;
x/=j;
}
}
//更优雅的方法
for (int i = 2;i <= x;i++)
{
if (zhishu[i])
{
zhi=0
for (int j = i;j <= x;;j*=i)
zhi+=x/j;
cnt[i]->change(zhi);
}
}
【完整代码】
/**************************************************************
Problem: 1005
User: chengchunyang
Language: C++
Result: Accepted
Time:36 ms
Memory:1316 kb
****************************************************************/
#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1100;
int n,d[N],m,tot,cnt[N];
int ans[N],len = 1;
bool bo[N];
void go(int t,int x)
{
rep1(i,2,t)
if (bo[i])
{
int num = 0;
for (int j = i;j <= t;j*=i)
num+=t/j;
cnt[i]+=x*num;
}
}
void cheng(int p)
{
int x = 0;
rep1(i,1,len)
{
ans[i] = ans[i]*p+x;
x = ans[i]/10;
ans[i]%=10;
}
while (x>0)
{
ans[++len] = x;
x = ans[len]/10;
ans[len]%=10;
}
}
bool is(int x)
{
rep1(i,2,int(sqrt(x)))
if (x%i==0)
return false;
return true;
}
int main()
{
//freopen("F:\\rush.txt","r",stdin);
rei(n);
rep1(i,1,n)
{
rei(d[i]);
if (d[i]==0) return puts("0"),0;
if (d[i]==-1)
m++;
else
d[i]--,tot+=d[i];
}
if (n-2<tot)
return puts("0"),0;
memset(bo,false,sizeof bo);
rep1(i,2,n-2)
if (is(i)) bo[i] = true;
go(n-2,1);
go(n-2-tot,-1);
rep1(i,1,n)
go(d[i],-1);
ans[1] = 1;
rep1(i,2,n)
rep1(j,1,cnt[i])
cheng(i);
rep1(i,1,n-2-tot)
cheng(m);
rep2(i,len,1)
printf("%d",ans[i]);
return 0;
}