版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82531452
解析:
是的又是第二题最难。。。
是的又是一道状压
。。。
而且这道题还卡空间(128MB)。。。
于是这道题就被我拿来练卡空间了。。。
然后时间就成了全 最慢,空间成了全 最小,不到第二小内存的一半。。。
说正事
考虑怎么凑成一个数 。。。
由于题目要求分出来的全部互质,也就是说 的同一质因子必须全部来自同一个数,设 ,则若一个数的 的次数必须要么为0要么为 ,不符合条件的全部舍弃。
由于 以内的数最多只有14个不同的质因子(2~41连乘),所以可以状压 ,要看出来还是挺不容易的。。。
对于 的数,我们不一定要分解它的质因数,我们通过哪些数能够凑成它来考虑怎么分解。
剩下的就是实现细节,看代码吧。
代码(空间只有2168 ):
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define pc putchar
#define gc getchar
#define cs const
inline
ll getint(){
re ll num=0;
re char c;
while(!isdigit(c=gc()));
while(isdigit(c))num=(num<<1)+(num<<3)+(c^48),c=gc();
return num;
}
inline
void outint(ll a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=(a-a/10*10)^48,a/=10;
while(ch[0])pc(ch[ch[0]--]);
}
inline
ll gcd(ll a,ll b){
re ll tmp=0;
while(b){
tmp=a-a/b*b;
a=b;
b=tmp;
}
return a;
}
bool mark[31624];//31623<sqrt(1e9)<31624
int prime[3411],pcnt;//其中只有3410个质数
inline
void linear_sieves(int len=31623){
for(int re i=2;i<=len;++i){
if(!mark[i])prime[++pcnt]=i;
for(int re j=1;i*prime[j]<=len;++j){
mark[i*prime[j]]=true;
if(i%prime[j]==0)break;
}
}
}
ll n;
int m;
bool flag1;
inline
bool check(ll x){
if(n==n/x*x&&gcd(x,n/x)==1)return true;
return false;
}
ll f[1<<15];
set<ll> num;
inline
void sieves(ll x){
for(int re i=1;i<=pcnt;++i){
if(x==x/prime[i]*prime[i])num.insert(prime[i]);
while(x==x/prime[i]*prime[i])x/=prime[i];
}
if(x>1)num.insert(x);
}
inline
bool check0(){
ll tt=n;
for(set<ll>::iterator it=num.begin();it!=num.end();++it){
while(tt==tt/(*it)*(*it))tt/=(*it);
}
if(tt>1)return false;
return true;
}
inline
ll trans(int x){
int cnt=0,res=0;
for(set<ll>::iterator it=num.begin();it!=num.end();++it){
if(x==x/(*it)*(*it))res|=(1<<cnt);
++cnt;
}
return res;
}
int a[501];
int main(){
linear_sieves();
n=getint();
m=getint();
for(int re i=1;i<=m;++i){
ll x=getint();
if(x==1){
--i;
--m;
flag1=true;
continue;
}
if(check(x)){
sieves(x);
a[i]=x;
}
else --i,--m;
}
if(!check0()){
pc('0');
return 0;
}
for(int re i=1;i<=m;++i){
a[i]=trans(a[i]);
}
f[0]=1;
int up=num.size();
for(int re i=0;i<(1<<up);++i){
if(f[i]!=0)
for(int re j=1;j<=m;++j){
if(a[j]>i&&(i&a[j])==0)
f[i|a[j]]+=f[i];
}
}
outint(f[(1<<up)-1]*(flag1?2:1));
return 0;
}