首页 > 其他分享 >CF895C Square Subsets 题解

CF895C Square Subsets 题解

时间:2024-04-06 18:12:28浏览次数:13  
标签:Square int 题解 CF895C 19 70 oplus dp

看到 \(a_i\le 70\) 后,发现 \(n\) 啥用没有,因为只需要枚举 \(1-70\) 选几个即可。

看到求完全平方数后,想到分解质因数,由于 \(a_i\le 70\),所以只有 \(19\) 个质数,可以进行状压 dp。

设 \(dp_{i,j}\) 表示枚举到 \(i\),状态为 \(j\) 的方案数,便有:

\[dp_{i,j}=dp_{i-1,j}+dp_{i-1,j \oplus x} \]

其中 \(x\) 为 \(i\) 分解后的状态。

当然,我们忽略了一些情况,没有考虑到我们有很多种达到标准的方式,比如你放 \(1\) 个和放 \(3\) 个效果一样,你放这 \(3\) 个和放那 \(3\) 个效果一样。

所以,放奇数个的方案数为(\(a_i\) 表示数列里有多少个 \(i\)):

\[C_{a_i}^1+C_{a_i}^3+……+C_{a_i}^{2\lfloor\frac{a_i}{2}\rfloor}=2^{a_i-1} \]

放偶数个的方案数为:

\[C_{a_i}^0+C_{a_i}^2+……+C_{a_i}^{2\lceil\frac{a_i}{2}\rceil}=2^{a_i-1} \]

所以:

\[dp_{i,j}=2^{a_i}(dp_{i-1,j}+dp_{i-1,j \oplus x}) \]

时间复杂度 \(O(n+70\times 2^{19})\),空间复杂度 \(O(70\times 2^{19})\),注意不要 \(T/MLE\)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll p=1e9+7;
const int N=75,M=1<<19;
int n,m,pr[25],t[N];
int dp[N][M+5],a[N];
ll qpow(ll x,int y){
    if(y<0) return 1;
    ll re=1;
    while(y){
        if(y&1) re=re*x%p;
        x=x*x%p;
        y>>=1;
    }return re;
}int main(){
    cin>>n;
    for(int i=1,x;i<=n;i++)
        cin>>x,a[x]++;
    memset(t,1,sizeof(t));
    t[1]=0;dp[0][0]=1;
    for(int i=2;i<=70;i++){
        if(t[i]) t[i]=++m,pr[m]=i;
        for(int j=1;j<=m&&pr[j]*i<=70;j++){
            t[i*pr[j]]=0;
            if(i%pr[j]==0) break;
        }
    }for(int i=1;i<=70;i++){
        int x=0,z=i;
        for(int j=1;pr[j]*pr[j]<=i;j++)
            while(z%pr[j]==0)
                x^=(1<<(j-1)),z/=pr[j];
        if(z>1) x^=(1<<(t[z]-1));
        int zjy=qpow(2,a[i]-1);
        for(int j=0;j<M;j++){
            dp[i][j]=(dp[i][j]+(ll)dp[i-1][j]*zjy%p)%p;
            if(a[i]) dp[i][j^x]=(dp[i][j^x]+(ll)dp[i-1][j]*zjy%p)%p;
        }
    }cout<<(dp[70][0]+p-1)%p;
    return 0;
}//Kaká

标签:Square,int,题解,CF895C,19,70,oplus,dp
From: https://www.cnblogs.com/chang-an-22-lyh/p/18117705/cf859c_square-subsets_tj

相关文章

  • 题解:AT_xmascon21_b Bad Mood
    AT_xmascon21_bBadMood题意给定你一个\(n\timesm\)的矩形。以一条对角线为基础上,制作一个无向图,该图的顶点对应于格子的共有\((m+1)\times(n+1)\)个顶点,画上的对角线对应于图的边。这种方式能形成的连通分量的数量为得分。求最小得分和最大得分。思路最小得分是好......
  • 题解:CF1918B Minimize Inversions
    CF1918BMinimizeInversions思路暴力一个一个的算,复杂度巨大。数学规律让逆序最少,也就是让升序更多。我们可以通过多组数据实验,最终我们会发现,将数列\(A\)减少一个逆序对,让数列\(B\)随着\(A\)变化,最多会只会增加一个逆序对。而让\(A\)相邻两个数保持升序,\(B\)相邻......
  • CF1934B Yet Another Coin Problem 题解
    CF1934BYetAnotherCoinProblem题解题意目前有\(5\)种硬币,面值分别为\(1,3,6,10,15\)。给你一个数字\(n\),求出可以凑出\(n\)的最少的硬币的数量。思路这道题,大多数的人大概会想到动态规划的方法。但是,我们应该有敢于创新的精神。于是我就想到了一个简单的数学方法......
  • CF1950B Upscaling题解
    CF1950BUpscaling题解题意给予你一个正整数\(n\),构造一个如图的字符矩阵。思路注意数据\(1\len\le20\),可以发现数据很小,于是我们可以暴力模拟。我们可以将两列看为一列,两行看为一行。然而我们可以发现缩成的一行的\(i\)等于被缩的两行的\({i\div2}\)的向上取整。......
  • P4551 最长异或路径 题解
    题目链接:最长异或路径看到树上路径问题,且是异或和这种,先思考树上前缀和转化为前缀和问题。如果我们预处理出\(pre[curr]\)表示\(curr\)这个点到根的前缀异或值,那么很显然我们路径的两个点\(u\)与\(v\)的\(pre[u]\opluspre[v]\)和传统的加法的树上前缀和并不一样,因为异......
  • 24.4.6 题解
    4.6模拟赛T1困难的图论题意:找出所有在且仅在1个简单环中的边,输出编号的异或和。一个错误的想法:找边双连通分量,看边数是否等于点数反例:正解是点双所以我在想,为什么是点双,不是边双呢?什么时候找点双,什么时候找边双呢?T2中等的字符串已知\(m\)个关键词\(s_i\),每出现......
  • CF1200E Compress Words 题解
    题目链接:CF或者洛谷注意到总字符串长度不超过\(1e6\),对于两个串之间找前后缀匹配,只要能暴力枚举长度,\(check\为\O(1)\),那么最后显然线性复杂度。可以考虑\(kmp\),也可以考虑字符串哈希,最好上双哈希,然后拼串显然是在尾部继续添加新的前缀哈希,这个需要添加的串可以单独由匹配......
  • 牛客小白月赛90题解
    A.小A的文化节#include<bits/stdc++.h>#defineintlonglong#defineendl"\n"usingnamespacestd;constintN=1e5+10,mod=1e9+7;intn,m,a[N];voidsolve(){ cin>>n>>m;for(inti=1;i<=n;i++)cin>>a[i];intres=0......
  • BNDS 2024/4/6模拟赛题解
    T1方程描述给出非负整数\(N\),统计不定方程\(X+Y^2+Z^3=N\)的非负整数解\((X,Y,Z)\)的数量。输入输入数据,包含一个非负整数\(N\)。输出输出数据,包含一个非负整数表示解的数量。数据范围40%的数据,\(N<=10000\)60%的数据,\(N<=10^8\)100%的数据,\(N<=10^{16}\)分析......
  • LG_B3951 [GESP样题 五级] 小杨的队列 题解
    比较简单的一道逆序对的题,甚至不用\(\Omicron(n\logn)\)的归并,只需要\(\Omicron(n^2)\)的优化冒泡。就是一个在队列里每次push一个元素,然后查找逆序对的问题。值得一提的是,这道题身高不重复,所以才能优化冒泡拿满分,不然的话就得老实用归并了。直接看代码吧。#include<b......