关闭

2016 ccpc网络赛

1101人阅读 评论(0) 收藏 举报
/*
    题意:给你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
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

2016 CCPC 中国大学生程序设计竞赛 合肥赛区 总结

今天是2016年10月19日… 比赛完了已经过了3天. 今天想起我的总结还没写..这次真的很有幸来到合肥赛区比赛 也感谢教练还是对我们的相信 我对合肥赛区并没有报太大的希望我感觉这次可能有3个...
  • zzz805
  • zzz805
  • 2016-10-19 16:24
  • 2497

2016中国大学生程序设计竞赛(ccpc 杭州)题解报告

2016中国大学生程序设计竞赛(ccpc 杭州)题解报告
  • queuelovestack
  • queuelovestack
  • 2016-10-31 22:04
  • 2566

CCPC2017-江苏省省赛总结

这次省赛总得来说还是达到了预期目标的,靠着队友carry拿到了一等奖(也就是银),但是在这个过程中还是暴露了不少问题的。 首先是比赛当天,我们18个人乘公交乘过了头,还好及时发现,赶在热身赛结束...
  • xj949967574
  • xj949967574
  • 2017-05-15 19:36
  • 977

2016中国大学生程序设计竞赛(ccpc 长春)题解报告

2016中国大学生程序设计竞赛(ccpc 长春)题解报告
  • queuelovestack
  • queuelovestack
  • 2016-10-04 17:42
  • 3581

2015CCPC题目总结(小菜持续更新)

现场赛教练嫌弃我们渣,没让我们去,没办法,小菜只能赛后开了场,DP略虚,也只能拿个铜。 hdu5540 给你两个2X2矩阵,可以旋转,判断是否相等,水之 #include #include #...
  • bryant03
  • bryant03
  • 2015-11-17 17:36
  • 1743

2016年数学建模美赛题目原文及翻译-A [个人思路]

使用模型确定哪个您的策略取决于形状和桶,该人在浴缸的形状/体积/温度的体积,和由该人在浴缸所作的运动的程度。如果对方使用了泡泡浴的添加剂,而最初填补了浴缸中清洗协助,这将如何影响你的模型的结果吗?
  • zhangty0223
  • zhangty0223
  • 2016-01-29 09:57
  • 13120

2016美赛MCM_A题解题思路

2016年美赛洗澡盆问题个人思路,如有错误,还请多多指教。
  • qq_27245709
  • qq_27245709
  • 2016-06-05 17:45
  • 3256

2016年数学建模美赛题目原文及翻译-C [个人思路]

PROBLEM C: The Goodgrant Challenge The Goodgrant Foundation is a charitable organization that wa...
  • zhangty0223
  • zhangty0223
  • 2016-01-29 10:02
  • 15060

(翻译)2016美国数学建模MCM F题(政策)翻译:难民移民政策建模

PROBLEM F:Modeling Refugee Immigration Policies  With hundreds of thousands of refugees mov...
  • u011292087
  • u011292087
  • 2016-01-29 11:45
  • 3824

2017年CCPC中南地区邀请赛总结

周六下午到的时候来到订的酒店楼下却发现酒店在装修,感叹湘潭人名写意的生活态度。来不及休息,赶紧带着行李参加热身赛。因为前辈有在比赛中失误重启的经历,我们特地重启了下看D盘是否会还原。热身赛题目比较简单...
  • survivorone
  • survivorone
  • 2017-06-02 00:02
  • 311
    个人资料
    • 访问:2749次
    • 积分:215
    • 等级:
    • 排名:千里之外
    • 原创:19篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条
    文章分类