2016 ccpc网络赛
来源:互联网 发布:c语言下载官方下载 编辑:程序博客网 时间:2024/05/17 09:26
/* 题意:给你n个数,问你从这n个选择一些数相乘后为完全平方数的个数? tag: 高斯消元 列方程 分析:对于每一个数我们有选和不选两种选择,我们将其看成变量xi。然后问题就转化成从n个数中选择一些使得这些数唯一分解式中 指数对2取模的异或和为0。 然后列出方程求出自由元的个数num答案就是2^num - 1*/#include <cstdio>#include <algorithm>#include <cstring>using namespace std;typedef long long LL;const int mod = 1000000007;int n;int pm[2000], npm;void get_prime() { bool is_heshu[2000 + 100]; memset(is_heshu, 0, sizeof(is_heshu)); for(int i=2; i<=2000; i++) { if(is_heshu[i]) continue; pm[npm++] = i; for(int j=i+i; j<=2000; j+=i) is_heshu[j] = true; }}int equ, var; //有equ个方程 var个变量int A[1000][1000];int free_num;int gauss() { free_num = 0; int k, col; for(k=0, col=0; k<equ&&col<var; k++,col++) { int max_r = k; for(int i=k+1; i<equ; i++) if(abs(A[i][col]) > abs(A[max_r][col])) max_r = i; if(max_r != k) for(int j=k; j<=var; j++) swap(A[k][j], A[max_r][j]); if(A[k][col] == 0) { k--; free_num++; continue; } for(int i=k+1; i<equ; i++) { if(A[i][col] == 0) continue; for(int j=col; j<=var; j++) A[i][j] ^= A[k][j]; } } for(int i=k; i<equ; i++) if(A[i][col] != 0) return -1; //无解 return free_num;}int qk_mod(int a, int b) { long long res = 1; while(b) { if(b&1) res = ((long long)res*(long long)a)%mod; a = ((long long)a*(long long)a)%mod; b >>= 1; } return res;}int main() { int T; scanf("%d", &T); get_prime();// printf("npm = %d\n", npm);// for(int i=0; i<npm; i++) printf("%d ", pm[i]);// printf("\n"); int kase = 0; while(T--) { scanf("%d", &n); memset(A, 0, sizeof(A)); for(int j=0; j<n; j++) { LL t; scanf("%lld", &t); for(int i=0; i<npm; i++) { LL cnt = 0, tp = t; while(tp%pm[i]==0 && tp) tp/=pm[i], cnt++; A[i][j] = cnt%2; } } equ = npm; var = n; int res = gauss(); printf("Case #%d:\n", ++kase);// printf("res = %d\n", res); if(res == -1) printf("0\n"); else printf("%d\n", qk_mod(2, res)-1); } return 0;}
<pre name="code" class="cpp">/* 题意:给你一个N*M的方格, 方格内本来有一些数字, 但是不幸的是数字消失了, 现在只记住了一些数字中的最小值得地方, 问你有多少种填数字的方案满足这些谷点? tag:dfs + 容斥 + 状态压缩dp 分析:我们考虑从小往大往格子里面填数字, 定义dp[i][j]为已经填了i个格子, X填涂的情况为j的方案数。 那么dp[i][j] = dp[i-1][j] * (往.填的方案数) + dp[i-1][k] k为j中的一个X没有填涂。 这种计数方法会使一些.的位置变成X, 比如...X, 我们可能会将X..X也计入, 因此下面就需要去重, 去重的时候我们使用 容斥原理即可。 参考论文: 状态压缩动态规划中的状态与时间*/#include <cstdio>#include <algorithm>#include <cstring>#include <map>using namespace std;typedef long long LL;const int mod = 772002;int N, M;char Map[10][10];LL dp[30][1<<12];int num1[1<<15];int cnt(int st) { int res = 0; for(int i=0; i<15; i++) if(((st>>i)&1) == 1) res++; return res;}int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};bool inside(int x, int y) { return (x>=0&&x<N&&y>=0&&y<M);}int judge(int x, int y, map<pair<int, int>, int>&mp, int st) { //看看当前.周围有没有没有涂过色的X for(int i=0; i<8; i++) { int nx = x + dx[i], ny = y + dy[i]; if(!inside(nx, ny)) continue; if(Map[nx][ny] == 'X' && ((st>>mp[make_pair(nx, ny)])&1)==0) return true; } return false;}int tp2[1<<14];LL calc() { memset(dp, 0, sizeof(dp)); int idx = 0; map<pair<int, int>, int> mp; for(int i=0; i<N; i++) for(int j=0; j<M; j++) if(Map[i][j] == 'X') mp[make_pair(i, j)] = idx++; for(int j=0; j<(1<<idx); j++) { //预处理X填涂的情况为j的时候可以往.填的方案数 int tp = 0; for(int r=0; r<N; r++) for(int c=0; c<M; c++) { if(Map[r][c] == 'X' && ((j>>mp[make_pair(r, c)])&1)==0) tp++; else if(judge(r, c, mp, j)) tp++; } int tp3 = N*M - tp; tp2[j] = tp3; } dp[0][0] = 1; for(int i=1; i<=N*M; i++) for(int j=0; j<(1<<idx); j++) { if(num1[j] > i) continue; for(int k=0; k<idx; k++) if(((j>>k)&1)==1) dp[i][j] += dp[i-1][j^(1<<k)]; dp[i][j] %= mod; int tp = tp2[j] - i + 1; if(tp > 0) dp[i][j] += tp*dp[i-1][j]; dp[i][j] %= mod; } return dp[N*M][(1<<idx)-1];}bool pan(int x, int y) { for(int i=0; i<8; i++) { int nx = x + dx[i], ny = y + dy[i]; if(!inside(nx, ny)) continue; if(Map[nx][ny] == 'X') return false; } return true;}LL ans;void dfs(int x, int y, int flog) { if(x==N) { if(!flog) ans += calc(); else ans -= calc(); ans = (ans%mod + mod)%mod; return ; } int tpx = x, tpy = y + 1; if(tpy == M) tpy = 0, tpx +=1; dfs(tpx, tpy, flog); if(Map[x][y]=='.' && pan(x, y)) { Map[x][y] = 'X'; dfs(x, y, flog^=1); Map[x][y] = '.'; }}int main() { int kase = 0; for(int i=0; i<(1<<14); i++) { num1[i] = cnt(i); } while(scanf("%d%d", &N, &M) == 2) { for(int i=0; i<N; i++) scanf("%s", Map[i]); ans = 0; bool flog = false; for(int i=0; i<N; i++) for(int j=0; j<M; j++) if(Map[i][j] == 'X'){ for(int k=0; k<8; k++) { int nx = i + dx[k], ny = j + dy[k]; if(!inside(nx, ny)) continue; if(Map[nx][ny] == 'X') flog = true; } } if(flog) { printf("Case #%d: 0\n", ++kase); continue; } dfs(0, 0, 0); printf("Case #%d: %lld\n",++kase, ans); } return 0;}
0 0
- 2016 ccpc网络赛
- 2016CCPC网络赛个人总结
- HDU-5835-Danganronpa【2016CCPC网络赛】
- ccpc网络赛 E
- 2017ccpc网络赛
- CCPC 网络赛 2017 经验总结
- ccpc网络赛Friend-Graph
- 记第一次ccpc网络赛
- 2017 CCPC 网络赛 1007
- [ccpc网络赛]Friend-Graph
- hdu 5838Mountain(2016 CCPC网络赛1007) 状压
- HDU-5832-A water problem【2016CCPC网络赛】
- HDU-5842-Lweb and String【2016CCPC网络赛】
- HDU-5833-Zhu and 772002【2016CCPC网络赛】【高斯消元】
- hdu5832-ccpc网络赛 -高精度取余
- hdu5832 CCPC 网络赛 同余求模定理
- 2017ccpc网络赛CaoHaha's staff
- 2017 ccpc 网络赛 Friend-Graph
- 知乎和简书的夜间模式实现套路(转)
- javascript获取网页各种高宽及位置总结
- Localizing Parts of Faces Using a Consensus of Exemplars
- Linq中如何实现inner join、left join
- 整数在计算机中的编码
- 2016 ccpc网络赛
- sys/queue.h
- Linux网络监控工具netstat、sar
- Spring xml设置
- 第一次
- RabbitMq、ActiveMq、ZeroMq 和 kafka 比较
- 如何通过关键字和搜索结果分析用户需求
- ubuntu You might want to run 'apt-get -f install' to correct these:
- PAT-Sign In and Sign Out (25)