sgu200--Cracking RSA(高斯消元问题5,求乘积为完全平方数的种数)

Cracking RSA

Time Limit:250MS     Memory Limit:65536KB     64bit IO Format:%I64d
& %I64u

Submit Status

Description

<script type="text/javascript" language="javascript" src="http://acm.sgu.ru/js/jquery.js"><script type="text/javascript" language="javascript" src="http://acm.sgu.ru/js/jquery.example.js"><script type="text/javascript" language="javascript" src="http://acm.sgu.ru/js/ui.datepicker.js"><script
type="text/javascript" language="javascript" src="http://acm.sgu.ru/js/jquery.js"><script type="text/javascript" language="javascript" src="http://acm.sgu.ru/js/jquery.example.js"><script type="text/javascript" language="javascript" src="http://acm.sgu.ru/js/ui.datepicker.js">

200. Cracking RSA

time limit per test: 0.25 sec.

memory limit per test: 65536 KB

input: standard

output: standard

The following problem is somehow related to the final stage of many famous integer factorization algorithms involved in some cryptoanalytical problems, for example cracking well-known RSA public key system.

The most powerful of such algorithms, so called quadratic sieve descendant algorithms, utilize the fact that if n = pq where p and q are large unknown primes needed to be found out, then if v 2=w 2 (mod
n), u ≠ v (mod n) and u ≠ -v (mod n), then gcd(v + w, n) is a factor of n (either p or q).

Not getting further in the details of these algorithms, let us consider our problem. Given m integer numbers b 1, b 2, ..., b m such that all their prime factors are from the
set of first t primes, the task is to find such a subset S of {1, 2, ..., m} that product of b i for i from S is a perfect square i.e. equal to u 2 for some integer u. Given such S we
get one pair for testing (product of S elements stands for v when w is known from other steps of algorithms which are of no interest to us, testing performed is checking whether pair is nontrivial, i.e. u ≠ v (mod n) and u ≠ -v (mod n)). Since we want to factor
n with maximum possible probability, we would like to get as many such sets as possible. So the interesting problem could be to calculate the number of all such sets. This is exactly your task.

Input

The first line of the input file contains two integers t and m (1 ≤ t ≤ 100, 1 ≤ m ≤ 100). The second line of the input file contains m integer numbers b i such that all their prime factors are from t first primes (for example,
if t = 3 all their prime factors are from the set {2, 3, 5}). 1 ≤ b i ≤ 10 9 for all i.

Output

Output the number of non-empty subsets of the given set {b i}, the product of numbers from which is a perfect square

Sample test(s)

Input


3 4  9 20 500 3

Output


3

给出n个数,每个数都是由前t个素数组成的,问成绩为完全平方数的子集有多少?

完全平方数,也就是所成绩的所有素数组成都是偶数个,由此可以列出方程组,方程为Map[i][j]第j个数的第i个素数个数是不是偶数,偶数为0,奇数为1,结果全部为0,找出一共有多少组,也就是说找出自由元数num1,然后2^num1 - 1,减去全为0的一组,就是结果。

注意1,求自由元的时候不能直接在j == n的时候计数,那样在n*n的矩阵中可以,如果不是的话要用n-i

注意2,求出的自由元会很大,2^num1是个大数,所以要模拟一下,因为2的倍数的最后一位是1,2,4,8,6,2,....所以最后直接将最后一位减一就可以了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int vis[1100] , prim[1100] , cnt ;
int Map[110][110] , a[110] ;
int s[10000] ;
void get_prim()
{
    int i , j  ;
    memset(vis,0,sizeof(vis)) ;
    memset(prim,0,sizeof(prim)) ;
    cnt = 0 ;
    for(i = 2 ; i < 1000 ; i++)
    {
        if( !vis[i] )
        {
            prim[cnt++] = i ;
        }
        for(j = 0 ; j < cnt ; j++)
        {
            if( prim[j]*i >= 1000 ) break ;
            vis[ prim[j]*i ] = 1 ;
            if( i % prim[j] == 0 ) break ;
        }
    }
    return ;
}
void swap1(int p,int q,int m)
{
    int i , temp ;
    temp = a[p] ;
    a[p] = a[q] ;
    a[q] = temp ;
    for(i = 0 ; i < m ; i++)
    {
        temp = Map[p][i] ;
        Map[p][i] = Map[q][i] ;
        Map[q][i] = temp ;
    }
    return ;
}
int gauss(int n,int m)
{
    int i , j , k , t , num1 = 0;
    for(i = 0 , t = 0 ; i < n && t < m ; i++ , t++)
    {
        for(j = i ; j < n ; j++)
            if( Map[j][t] )
                break ;
        if( j == n )
        {
            i-- ;
            continue ;
        }
        if( i != j )
            swap1(i,j,m) ;
        for(j = i+1 ; j < n ; j++)
        {
            if( Map[j][t] == 0 ) continue ;
            a[j] ^= a[i] ;
            for(k = t ; k < m ; k++)
            {
                Map[j][k] ^= Map[i][k] ;
            }
        }
    }
    return m - i ;
}
int main()
{
    int t , m , i , j , x , num1 ;
    get_prim() ;
    memset(Map,0,sizeof(Map)) ;
    scanf("%d %d", &t, &m) ;
    for(j = 0 ; j < m ; j++)
    {
        scanf("%d", &x) ;
        for(i = 0 ; i < t  ; i++)
        {
            a[i] = 0 ;
            num1 = 0 ;
            while( x % prim[i] == 0 )
            {
                num1++ ;
                x /= prim[i] ;
            }
            Map[i][j] = num1 % 2 ;
        }
    }
    num1 = gauss(t,m) ;
    s[0] = 1 ;
    cnt = 1 ;
    int temp , k ;
    for(i = 0 ; i < num1 ; i++)
    {
        temp = 0 ;
        for(j = 0 ; j < cnt ; j++)
        {
            k = s[j]*2 + temp ;
            s[j] = k%10 ;
            temp = k/10 ;
        }
        if( temp != 0 )
            s[cnt++] = temp ;
    }
    s[0] -= 1 ;
    for(i = cnt-1 ; i >= 0 ; i--)
    {
        printf("%d", s[i]) ;
    }
    printf("\n") ;
    return 0;
}

时间: 2024-08-28 18:43:00

sgu200--Cracking RSA(高斯消元问题5,求乘积为完全平方数的种数)的相关文章

Acdream1217 Cracking&#39; RSA(高斯消元)

题意:给你m个数(m<=100),每个数的素因子仅来自于前t(t<=100)个素数,问这m个数的非空子集里,满足子集里的数的积为完全平方数的有多少个. 一开始就想进去里典型的dp世界观里,dp[n][mask]表示前n个数里为mask的有多少个,但显然这里t太大了.然后又YY了很多很多.像m少的时候应该用的是高消.即对每个因子列一个xor方程,然后高斯消元,其中自由元的个数就是可以随便取的,所以答案是2^(自由元个数),然后把空集的减掉,就是2^(自由元)-1,不过大数是必须的. #inclu

SGU 200. Cracking RSA(高斯消元+高精度)

题目大意:给出m个整数,因子全部存在于前t个素数.问有多少个子集,他们的乘积是平方数. 解题思路: 完全平方数就是要求每个质因子的指数是偶数次. 对每个质因子建立一个方程. 变成模2的线性方程组. 求解这个方程组有多少个自由变元,答案就是 2^p - 1 .(-1是去掉空集的情况) 注意由于2^p会超出数据范围所以还需要用高精度算法. 200. Cracking RSA time limit per test: 0.25 sec. memory limit per test: 65536 KB

SGU 200.Cracking RSA(高斯消元)

时间限制:0.25s 空间限制:4M 题意: 给出了m(<100)个数,这m个数的质因子都是前t(<100)个质数构成的. 问有多少个这m个数的子集,使得他们的乘积是完全平方数. Solution: 要使乘积为完全平方数,那么对于乘积的每个质因子的个数要为偶数. 可以先打出前100个质数,来看第i个质数Pi,对于第j个数Kj,如果它含有奇数个质数Pi,那么矩阵A[i][j]的值为1,显然增广矩阵的值应该全为0. 这样就构造出了一个n*m的xor方程组. 利用高斯消元求出变元的个数power 那

POJ 1753 Flip Game (高斯消元 枚举自由变元求最小步数)

题目链接 题意:4*4的黑白棋,求把棋全变白或者全变黑的最小步数. 分析:以前用状态压缩做过. 和上题差不多,唯一的不同是这个终态是黑棋或者白棋, 但是只需要把给的初态做不同的两次处理就行了. 感觉现在还只是会套模板,不能独立的思考,好伤心.... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath&g

Light OJ 1272 Maximum Subset Sum 高斯消元 最大XOR值

题目来源:Light OJ 1272 Maximum Subset Sum 题意:选出一些数 他们的抑或之后的值最大 思路:每个数为一个方程 高斯消元 从最高位求出上三角 消元前k个a[i]异或和都能有消元后的异或和组成 消元前 k 个 a[i] a[i]异或和都能有消元后的 异或和都能有消元后的 p 个 a[i] a[i]的异或 的异或 保证每一列只有一个1 消元后所有A[i]抑或起来就是答案 #include <cstdio> #include <cstring> #inclu

SGU 200 Cracking RSA (高斯消元+大数高精度)

题目地址:SGU 200 这题居然还考大数高精度..无语.. 令有该因子偶数个为0,奇数个为1,这样就满足异或运算了,即奇+奇=偶,偶+偶=偶,奇+偶=奇.然后建立方程高斯消元求变元个数free_num,那么子集的个数就是2^free_num-1.减1是去掉0的情况.注意要用大数运算 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #includ

poj_1222_高斯消元

第一次学习使用高斯消元,将灯板化为线性方程组,进行求解. /*######################################################################### # File Name: poj_1222.cpp # Author: CaoLei # Created Time: 2015/7/20 15:48:04 ###################################################################

HDU 4870 Rating(高斯消元)

HDU 4870 Rating 题目链接 题意:一个人注册两个账号,初始rating都是0,他每次拿低分的那个号去打比赛,赢了加50分,输了扣100分,胜率为p,他会打到直到一个号有1000分为止,问比赛场次的期望 思路:f(i, j)表示i >= j,第一个号i分,第二个号j分时候,达到目标的期望,那么可以列出转移为f(i, j) = p f(i', j') + (1 - p) f(i'' + j'') + 1 f(i', j')对应的是赢了加分的状态,f(i'', j'')对应输的扣分的状态

【BZOJ 4171】 4171: Rhl的游戏 (高斯消元)

4171: Rhl的游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 74  Solved: 33[Submit][Status][Discuss] Description RHL最近迷上一个小游戏:Flip it.游戏的规则很简单,在一个N*M的格子上,有一些格子是黑色,有一些是白色 .每选择一个格子按一次,格子以及周围边相邻的格子都会翻转颜色(边相邻指至少与该格子有一条公共边的格子 ),黑变白,白变黑.RHL希望把所有格子都变成白色的.不幸