题目传送门

题目大意

给出一个数 \(n\),你要构造一个数列,满足里面每个数都是 \(n\) 的因子,且每一个数与前面不互质的个数不超过 \(1\)。问有多少种合法方案。

保证 \(n\) 的不同质因子个数 \(\le 6\)。

思路

这个题不是很难,只是比较难写。不过 \(\Theta(6\times 3^6)\) 的做法感觉比较有意思,但是我写的是玄学时间复杂度的做法。

我们可以看出数列长度最大也就 \(12\),而且质因子个数也很少,不难想到状压 dp,我们发现这个状压 dp 完全没有什么难点,直接 \(f_{S,x}\) 表示当前状态为 \(S\),已经填了 \(x\) 位的方案数。对于一个状态,肯定是每个质因子的状态组合起来,你发现重要的不过就是这个质因子出现了几次,如果只出现一次是哪些质因子一起出现的。你把这个压进状态就好了。

似乎预处理了之后转移可以更快,但是懒得了。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define mod 1000000007
#define ll long long template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} ll N;
int cnt,yz[15],pw[15]; int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
void Mul (int &a,int b){a = mul (a,b);}
void Dec (int &a,int b){a = dec (a,b);}
void Add (int &a,int b){a = add (a,b);} void Makeyz (ll n){
for (Int i = 2;1ll * i * i <= n;++ i){
if (n % i == 0){
yz[++ cnt] = i;
while (n % i == 0) n /= i,pw[cnt] ++;
}
}
if (n > 1) yz[++ cnt] = n,pw[cnt] = 1;
} int f[1 << 19][15]; signed main(){
read (N),Makeyz (N);
f[0][0] = 1;int ans = 0;
for (Int x = 0;x < cnt * 2;++ x){
for (Int nowS = 0;nowS < (1 << cnt * 3);++ nowS){
if (!f[nowS][x]) continue;
vector <int> unused,cho;
bool used[12] = {};
for (Int i = 1;i <= cnt;++ i){
int k = nowS >> (i - 1) * 3 & 7;
if (!k) unused.push_back (i);
else if (k < 7 && !used[k]) cho.push_back (i),used[k] = 1;
}
int siz1 = unused.size(),siz2 = cho.size();
for (Int S = 0;S < (1 << siz1);++ S){
int kase = 1,S1 = 0,fir = 0;
for (Int i = 0;i < siz1;++ i) if (S >> i & 1)
fir = fir ? fir : unused[i],Mul (kase,pw[unused[i]]),S1 |= (1 << (unused[i] - 1) * 3) * fir;
if (S) Add (f[nowS | S1][x + 1],mul (kase,f[nowS][x]));
if (!cho.size()) continue;
for (Int u : cho){
int k = nowS >> (u - 1) * 3 & 7,siz2 = 0;
vector <int> uni;
for (Int i = 1;i <= cnt;++ i) if ((nowS >> (i - 1) * 3 & 7) == k) uni.push_back (i);
siz2 = uni.size();
for (Int choS = 1;choS < (1 << siz2);++ choS){
int newS = nowS | S1,fir = 0x7f7f7f7f,kase1 = 1;
for (Int i = 0;i < siz2;++ i)
if (choS >> i & 1) newS -= (1 << (uni[i] - 1) * 3) * (k - 7),Mul (kase1,pw[uni[i]]);
else fir = min (fir,uni[i]);
for (Int i = 0;i < siz2;++ i) if (!(choS >> i & 1)) newS -= (1 << (uni[i] - 1) * 3) * (k - fir);
Add (f[newS][x + 1],mul (f[nowS][x],mul (kase,kase1)));
}
}
}
}
}
for (Int x = 1;x <= cnt * 2;++ x) for (Int nowS = 0;nowS < (1 << cnt * 3);++ nowS) Add (ans,f[nowS][x]);
write (ans),putchar ('\n');
return 0;
}

最新文章

  1. JS - 柯里化
  2. 给RecyclerView最纯粹的下拉刷新和上拉加载更多
  3. iOS开发
  4. C#数据库导出(入)TXT
  5. x01.BitmapHelper:图像处理
  6. Java多线程题库
  7. Nginx 上的 php-fpm 资源侵占问题
  8. linux资源监控命令详解
  9. poj 2185(二维kmp)
  10. 2.里氏替换原则(Liskov Substitution Principle)
  11. 域名服务器--DNS
  12. hdoj 1285 确定比赛名次【拓扑排序】
  13. CentOS下命令行和桌面模式的切换方法(转载)
  14. PHP进度条
  15. JAVA线程概念
  16. vue-cli 的项目 切换到Linux环境下遇到问题
  17. MySQL 字符集和校对
  18. Redis的中并发问题的解决方案小结
  19. Filebeat插件启动失败,不能直接查找报错原因
  20. 一种基于SDR实现的被动GSM嗅探

热门文章

  1. Java反射的浅显理解
  2. Linux centos7 find 命令
  3. openresty(nginx) 配置 http与https使用同一个端口,禁止 IP 直接访问
  4. mybatis动态sql以及分页
  5. windows系统框架
  6. SQL-INSERT触发器练习
  7. MongoDB索引的简单理解
  8. 除PerfDog之外,还有什么性能测试工具。
  9. 一文带你了解.Net读写锁
  10. 论文解读(PCL)《Prototypical Contrastive Learning of Unsupervised Representations》