CF895C Square Subsets (组合数+状压DP+简单数论)

题目大意:给你一个序列,你可以在序列中任选一个子序列,求子序列每一项的积是一个平方数的方案数。

1<=a[i]<=70

因为任何一个大于2的数都可以表示成几个质数的幂的乘积

所以我们预处理70以内的质数,把它作为二进制状压的状态,每个在序列中出现数Hash一下,组合数推一下

所以把奇次幂的状态表示为1,偶次幂的状态就是0,比如6就是11,42就是1011

而平方数的每个质因子的指数都是偶数,所以最终结果的状态就是0000000...

转移的过程,两个数的乘积,就是这两个数的质因子二进制的状态的合并,即异或(xor)运算

卡常很恶心,懒得进一步优化了

好吧据说可以推出结论,这个组合数加起来其实是2的幂次

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #define N 100100
 5 #define M 75
 6 #define mod 1000000007
 7 #define C(m,n) (((fac[n]*inv[m])%mod*inv[n-m])%mod)
 8 #define ll long long
 9 using namespace std;
10
11 int xx,n,now,lst;
12 int hx[M];
13 ll x,y,t;
14 ll inv[N],fac[N],f[2][(1<<19)+100];
15 int pr[19]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67};
16 int gc()
17 {
18     int rett=0,fh=1;char c=getchar();
19     while(c<‘0‘||c>‘9‘) {if(c==‘-‘)fh=-1; c=getchar();}
20     while(c>=‘0‘&&c<=‘9‘) {rett=rett*10+c-‘0‘;c=getchar();}
21     return rett*fh;
22 }
23 void exgcd(ll a,ll b)
24 {
25     if(b==0) {x=1,y=0;}
26     else {exgcd(b,a%b);t=x;x=y;y=t-a/b*y;}
27 }
28 void get_inv()
29 {
30     inv[0]=inv[1]=1,fac[0]=fac[1]=1;
31     for(ll i=2;i<=n;i++)
32     {
33         exgcd(i,mod);
34         fac[i]=(fac[i-1]*i)%mod;
35         x=(x%mod+mod)%mod;
36         inv[i]=(inv[i-1]*x)%mod;
37     }
38 }
39
40 int main()
41 {
42     //freopen("aa.in","r",stdin);
43     scanf("%d",&n);
44     for(int i=1;i<=n;i++) xx=gc(),hx[xx]++;
45     get_inv();
46     now=1,lst=0,f[0][0]=1;
47     for(int i=1;i<=70;i++)
48     {
49         if(!hx[i]) continue;
50         int s=0,x=i;
51         for(int j=0;j<19;j++)
52         {
53             while(x%pr[j]==0)
54             {
55                 s^=(1<<j);
56                 x/=pr[j];
57             }
58         }
59         for(int p=0;p<(1<<19);p++)
60         {
61               if(!f[lst][p]) continue;
62             for(int j=0;j<=hx[i];j++)
63             {
64                 if(j&1)
65                 {
66                     f[now][p^s]+=(f[lst][p]*C(j,hx[i]))%mod;
67                     f[now][p^s]%=mod;
68                 }else{
69                     f[now][p]+=(f[lst][p]*C(j,hx[i]))%mod;
70                     f[now][p]%=mod;
71                 }
72             }
73             f[lst][p]=0;
74         }
75         swap(now,lst);
76     }
77     printf("%I64d\n",f[lst][0]-1);
78     return 0;
79 }
80
81
82     

原文地址:https://www.cnblogs.com/guapisolo/p/9696976.html

时间: 2024-08-19 11:41:45

CF895C Square Subsets (组合数+状压DP+简单数论)的相关文章

Codeforces 895C Square Subsets(状压DP 或 异或线性基)

题目链接  Square Subsets 这是白书原题啊 先考虑状压DP的做法 2到70总共19个质数,所以考虑状态压缩. 因为数据范围是70,那么我们统计出2到70的每个数的个数然后从2考虑到70. 设dp[x][mask]为考虑到x这个数的时候,x这个数和之前的所有数中,选出某些数,他们的乘积分解质因数,所有的指数对2取模之后, 状态为mask的方案数. 然后就可以转移了……这个状压DP花了我好几个小时……真是弱啊 哦对最后还要特判1的情况. 每个1选或不选都可以,然后考虑只选1的情况,累加

POJ 3311 Hie with the Pie (Floyd + 状压dp 简单TSP问题)

Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5019   Accepted: 2673 Description The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortunately, due to cutbacks, they can affo

URAL 1152 Faise Mirrors 状压DP 简单题

1152. False Mirrors Time limit: 2.0 secondMemory limit: 64 MB Background We wandered in the labyrinth for twenty minutes before finally entering the large hall. The walls were covered by mirrors here as well. Under the ceiling hung small balconies wh

POJ 3254 简单状压DP

没什么可说的,入门级状压DP,直接撸掉 #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <cmath> #include <vector> #include <map> #include <queue> #include <stac

NOJ 1116 哈罗哈的大披萨 【淡蓝】 [状压dp+各种优化]

我只能说,珍爱生命,远离卡常数的题...感谢陈老师和蔡神,没有他们,,,我调一个星期都弄不出来,,,, 哈罗哈的大披萨 [淡蓝] 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 73            测试通过 : 9 描述 热风哈罗哈(三牌楼)店正在搞活动:他们将提供一个大披萨给第一个告诉他们以下信息的人:一次购买任一种披萨,哪种单位面积的价格最低.问题初步想一想,好像是这么解决:“对于每个披萨计算平均

hdu4739(状压DP)

Zhuge Liang's Mines Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1318    Accepted Submission(s): 557 Problem Description In the ancient three kingdom period, Zhuge Liang was the most famous

BZOJ 1087: [SCOI2005]互不侵犯King( 状压dp )

简单的状压dp... dp( x , h , s ) 表示当前第 x 行 , 用了 h 个 king , 当前行的状态为 s . 考虑转移 : dp( x , h , s ) = ∑ dp( x - 1 , h - cnt_1( s ) , s' ) ( s and s' 两行不冲突 , cnt_1( s ) 表示 s 状态用了多少个 king ) 我有各种预处理所以 code 的方程和这有点不一样 ------------------------------------------------

状压dp入门

(先处理好基本的位运算的东西) 为了更好的理解状压dp,首先介绍位运算相关的知识. 1.'&'符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值.例如3(11)&2(10)=2(10). 2.'|'符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值.例如3(11)|2(10)=3(11). 3.'^'符号,x^y,会将两个十进制数在二进制下进行异或运算,然后返回其十进制下的值.例如3(11)^2(10)=1(01). 4.'<&

[NOIP2016]愤怒的小鸟 D2 T3 状压DP

[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如y=ax2+bx的曲线,其中a,b是Kiana指定的参数,且必须满足a<0. 当小鸟落回地面(即x轴)时,它就会瞬间消失. 在游戏的某个关卡里,平面的第一象限中有n只绿色的小猪,其中第i只小猪所在的坐标为(xi,yi). 如果某只小鸟的飞行