↓ Skip to main content
  1. Posts/

hdu 5833 || ccpc 2016 网络赛 1002 Zhu and 772002 (高斯消元)

·528 words·2 mins
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

hdu 5833 题目链接

题意:n个数,保证每个数的素因子不超过2000,从中取若干个,问乘积是完全平方数的方案数。

思路: 完全平方数就是要求每个质因子的指数是偶数次。

列方程组,a1,a2,a3……am分别表示bi是否在集合中。对于每一个素因子,建立异或方程组,要求因子个数为偶数,即异或为0

然后得到自由元的个数为num,答案为2^num-1 (减去空集)

代码实现
  1#include <iostream>
  2#include <string.h>
  3#include <math.h>
  4#include <queue>
  5#include <algorithm>
  6#include <stdlib.h>
  7#include <map>
  8#include <set>
  9#include <stdio.h>
 10using namespace std;
 11typedef long long LL ;
 12#define pi acos(-1.0)
 13const int mod=1e9+7;
 14const int INF=1e9;
 15const double eqs=1e-9;
 16const int N=310;
 17LL mat[N][N], a[N], equ, var, prime[N];
 18LL c[N];
 19LL gauss()
 20{
 21    LL i, j, k, h, max_r, tmp;
 22    for(i=0,j=0;i<equ&&j<var;i++,j++){
 23	max_r=i;
 24	for(k=i+1;k<equ;k++){
 25	    if(mat[k][j]>mat[max_r][j]) max_r=k;
 26	}
 27	if(max_r!=i){
 28	    for(k=j;k<=var;k++){
 29		swap(mat[i][k],mat[max_r][k]);
 30	    }
 31	}
 32	if(mat[i][j]==0){
 33	    i--;
 34	    continue ;
 35	}
 36	for(k=i+1;k<equ;k++){
 37	    if(mat[k][j]==0) continue ;
 38	    for(h=j;h<=var;h++){
 39		mat[k][h]^=mat[i][h];
 40	    }
 41	}
 42    }
 43    tmp=i;
 44    //printf("%d\n",tmp);
 45    for(;i<equ;i++){
 46	if(mat[i][var]){
 47	    return 0;
 48	}
 49    }
 50    return var-tmp;
 51}
 52void output(int k)
 53{
 54    LL i, j, x, y, tmp;
 55    memset(c,0,sizeof(c));
 56    c[0]=1;
 57    x=0;
 58    for(i=0;i<k;i++){
 59	for(j=0;j<=80;j++){
 60	    y=(c[j]*2+x);
 61	    x=(c[j]*2+x)/10;
 62	    c[j]=y;
 63	}
 64    }
 65    for(i=80;i>=0;i--){
 66	if(c[i]){
 67	    tmp=i;
 68	    break;
 69	}
 70    }
 71    c[0]--;
 72    for(i=tmp;i>=0;i--){
 73	printf("%lld",c[i]);
 74    }
 75    puts("");
 76}
 77void init()
 78{
 79    LL i, j, cnt=0, flag;
 80    for(i=2;;i++){
 81	flag=0;
 82	for(j=2;j*j<=i;j++){
 83	    if(i%j==0){
 84		flag=1;
 85		break;
 86	    }
 87	}
 88	if(!flag){
 89	    prime[cnt++]=i;
 90	}
 91	if(cnt==305) return ;
 92    }
 93}
 94LL ksm(LL a,LL b)
 95{
 96    LL res = 1LL;
 97    while (b>0)
 98    {
 99	if (b&1)
100	    res = (res*a)%MOD;
101	b = b/2;
102	a = (a*a)%MOD;
103    }
104
105    return res;
106}
107
108int main()
109{
110
111  //  freopen("code/in.txt","r",stdin);
112    LL t, n, i, j, x, cnt, ans;
113    int T;
114    cin>>T;
115    int cas = 0 ;
116    while (T--){
117	printf("Case #%d:\n",++cas);
118	init();
119	scanf("%lld",&n);
120	t = 305;
121	for(i=0; i<n; i++) {
122	    scanf("%lld",&a[i]);
123	}
124	for(i=0; i<n; i++) {
125	    x=a[i];
126	    for(j=0;j<t;j++){
127		cnt=0;
128		while(x%prime[j]==0){
129		    cnt++;
130		    x/=prime[j];
131		}
132		mat[j][i]=(cnt&1);
133	    }
134	}
135	for(i=0;i<t;i++){
136	    mat[i][n]=0;
137	}
138	equ=t;
139	var=n;
140	ans=gauss();
141	if(ans)
142	    printf("%lld\n",ksm(2,ans)-1);
143	else puts("0");
144    }
145	    return 0;
146}

Related

hdu 2050 折线分割平面 (找规律,递推)

·246 words·1 min
hdu 2050题目链接 题意:n条折线。。最多能把平面分成几部分。。 思路:联想到m条直线,最多能把平面分成m*(m+1)/2+1部分。。 画图发现。。。 f[2*n-1]==g[n]。。

whust2016 warm up A ||codeforces 682 A. Alyona and Numbers (计数问题,水)

·294 words·1 min
cf682A题目链接 题意:两个数组,分别为1..n和1..m。。。从两个数组中各取一个,问和能被5整除的方案数。。。 思路:傻逼题。。。统计%5。。。然后乘法原理。。 代码实现 1/* *********************************************** 2Author :111qqz 3Created Time :2016年07月18日 星期一 12时32分22秒 4File Name :code/2016whust/A.cpp 5************************************************ */ 6 7#include <cstdio> 8#include <cstring> 9#include <iostream> 10#include <algorithm> 11#include <vector> 12#include <queue> 13#include <set> 14#include <map> 15#include <string> 16#include <cmath> 17#include <cstdlib> 18#include <ctime> 19#define fst first 20#define sec second 21#define lson l,m,rt<<1 22#define rson m+1,r,rt<<1|1 23#define ms(a,x) memset(a,x,sizeof(a)) 24typedef long long LL; 25#define pi pair < int ,int > 26#define MP make_pair 27 28using namespace std; 29const double eps = 1E-8; 30const int dx4[4]={1,0,0,-1}; 31const int dy4[4]={0,-1,1,0}; 32const int inf = 0x3f3f3f3f; 33const int N=1E6+7; 34int n,m; 35LL a[N],b[N]; 36int main() 37{ 38 #ifndef ONLINE_JUDGE 39 freopen("code/in.txt","r",stdin); 40 #endif 41 42 cin>>n>>m; 43 ms(a,0); 44 ms(b,0); 45 for ( int i = 1 ; i <= n ; i++) 46 { 47 int x = i % 5; 48 a[x]++; 49 } 50 for ( int i = 1 ; i <= m ; i++) 51 { 52 int x = i % 5; 53 b[x]++; 54 } 55 LL ans = 0; 56 ans = a[0]*b[0]+a[1]*b[4]+a[2]*b[3]+a[3]*b[2]+a[4]*b[1]; 57 cout<<ans<<endl; 58 59 #ifndef ONLINE_JUDGE 60 fclose(stdin); 61 #endif 62 return 0; 63}

hdu 4607 Park Visit (树的直径,推公式)

·748 words·2 mins
hdu4607题目链接 题意:给出一棵树。。。边权都为1. m个查询。。每个查询给一个k,表示只访问k个点。。。问每次的最小路径和是多少。。。 思路:我们发现。。会使路径和变大的一个不利因素是折返。。也就是访问某景点后。。必须要回去才能继续前进。。这样的距离是2倍。。那为了使得路径和尽可能小。。我们就尽量不要访问这样的点。。。而不是这样的点一定在直径上。。。以及我们还发现。。。不在直径上的点。。 。。不管深度如何(深度的意思是说,与和该点最近的直径上的点的距离),距离的贡献是一样的。。都是2倍。。所以我们可以推出一个公式。。。如果树的直径是d,那么k<=d+1的时候,答案为k-1,否则答案为d+(k-d-1)*2。。。

hdu 5630 Rikka with Chess (暴力 ,计数问题)

·287 words·1 min
http://acm.hdu.edu.cn/showproblem.php?pid=5630 题意:nm的棋盘,相邻格子的颜色相反,每次可以翻转一个任意大小矩形的格子,问最少需要翻转多少次使得棋盘的nm个格子颜色相同。(翻转的意思是颜色反色) 思路:手写了下。。发现。。答案就是n/2+m/2. 对应的最优策略是。。翻偶数行和偶数列,都翻一遍,颜色就一样了。