分解质因数
完全平方数
分析
https://www.jianshu.com/p/888f2c2b31bc
注意系数摆放顺序
素数 2 3 5
4: 2 0 0
6: 1 1 0
10: 1 0 1
15: 0 1 1
每个数对应的次数序列 依次列摆,得矩阵
2 1 1 0 0 0 1 1 0 0
0 1 0 1 0 0 1 0 1 0
0 0 1 1 0 mod2 之后 =》 0 0 1 1 0
然后异或消元,求得矩阵的秩R(A)
自由变元个数=n-R(A)
变量有 1 或 0 两种取值选择 所以 解的个数为 2^m (m为自由元的个数)
题中要求至少选择一个数(即至少有一个自由元的取值为1),那么要抛出自由元均为0的情况
所以最终有 2^m - 1种组合
思路
分解质因数,质因子的次数为偶数记为0 奇数记为1,求得矩阵,注意矩阵的顺序
异或消元 求出矩阵的秩 从而自由元有 n-r个 从而得出解的个数
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#define mm 1000000007
using namespace std;
typedef long long ll;
const int maxn = 2100; // 表长
int prime[maxn],cnt ; // prime记录素数,pNum记录素数个数,///i的最小质因子
bool vis[maxn] ; // p记录当前数是否被筛去
void eess(int n) // 查找记录2-n的素数
{
cnt=0;
vis[0]=vis[1]=1;
for (int i = 2; i <= n; i++)
{
if (!vis[i]) // 如果未被筛过,则为素数
{prime[cnt++] = i;} ///从0开始
for (int j = 0; j < cnt&&i * prime[j] <= n; j++)
{ // 当要标记的合数超出范围时跳出
vis[i * prime[j]] = 1; // 将已经记录的素数的倍数进行标记
if (i % prime[j] == 0) //关键步骤
break;
}
}
}
int A[310][310];//系数矩阵
int Gauss(int m,int n){//m个方程 n个变量
int i=0,j=0,k,r,u;
while(i<m&&j<n){
r=i;
for(k=i;k<m;k++){
if(A[k][j]){
r=k;break;
}
}///从第i行开始向下找 第一个第j列的数不为0的行
if(A[r][j]){
if(r!=i)///如果第找到的这一行不是初始行(第i行),那么交换两行
for(k=0;k<n;k++)swap(A[r][k],A[i][k]);
for(u=i+1;u<m;u++)///将第i行后面的每一行的第j列元素消为0
if(A[u][j])///第j列不为0
for(k=0;k<n;k++)
A[u][k]^=A[i][k];///异或消元 1^1=0
i++;
}
j++;
}
return i;
}
ll mul(ll a, ll b, ll m)
//求a*b%m
{
ll ans = 0;
a %= m;
while(b)
{
if(b & 1)ans = (ans + a) % m;
b /= 2;
a = (a + a) % m;
}
return ans;
}
ll ppow(ll a, ll b)
//a^b % m
{
ll ans = 1;
a %= mm;
while(b)
{
if(b & 1)ans = mul(a, ans, mm);
b /= 2;
a = mul(a, a, mm);
}
ans %= mm;
return ans;
}
int main()
{
eess(2050);
int T;
cin>>T;
for(int ca=1;ca<=T;ca++)
{
ll n,p,maxp=0;
memset(A,0,sizeof(A));
cin>>n;
for(ll i=0;i<n;i++)
{
cin>>p;
for(ll j=0;j<303;j++)
{
while(p%prime[j]==0)
{
maxp=max(maxp,j);
p/=prime[j];///分解质因数
A[j][i]^=1;///偶数为0 奇数为1
}
}
}
ll r=Gauss(maxp+1,n);
ll ans=ppow(2,n-r);
cout<<"Case #"<<ca<<":"<<endl;
cout<<ans-1<<endl;
}
return 0;
}