zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 南京赛区网络预赛 K. The Great Nim Game(博弈)

    题目链接:https://nanti.jisuanke.com/t/31000

    题意:有N堆石子(N为大数),每堆的个数按一定方式生成,问先手取若干堆进行尼姆博弈,必胜的方式有多少种。      

    题解:因为 k < 4096,所以出现的数最多只有4096个,对每个数字只考虑出现奇/偶次进行dp,答案是所有不等于0的dp值的和。然后如果一个数字出现x次,它对自己出现奇数次的方案数和偶数次的方案数贡献都是乘上2 ^ (x - 1),每个数字的贡献都是2 ^ (x - 1) 总贡献就是2 ^ (N - ∑(vis[i]))。大数可以一边读入一边取模。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define ll long long
      4 #define ull unsigned long long
      5 #define mst(a,b) memset((a),(b),sizeof(a))
      6 #define mp(a,b) make_pair(a,b)
      7 #define fi first
      8 #define se second
      9 #define pi acos(-1)
     10 #define pii pair<int,int>
     11 const int INF = 0x3f3f3f3f;
     12 const double eps = 1e-6;
     13 const int MAXN = 1e7 + 10;
     14 const int MAXM = 2e6 + 10;
     15 const ll mod = 1e9 + 7;
     16 
     17 bool vis[4105];
     18 int dp[2][8192];
     19 vector<int>vec;
     20 int f[4105];
     21 
     22 ll pow_mod(ll a, ll n) {
     23     ll ans = 1;
     24     while(n) {
     25         if(n & 1) ans = ans * a % mod;
     26         a = a * a % mod;
     27         n >>= 1;
     28     }
     29     return ans;
     30 }
     31 
     32 int main() {
     33 #ifdef local
     34     freopen("data.txt", "r", stdin);
     35 //    freopen("data.txt", "w", stdout);
     36 #endif
     37     ll ans = 0;
     38     char ch;
     39     int len = 0;
     40     int n = 1e9;
     41     while(1) {
     42         scanf("%c", &ch);
     43         if(ch == ' ') break;
     44         ans = pow_mod(ans, 10);
     45         if(len == 0) ans = 1;
     46         ans = ans * (1ll << (ch - '0')) % mod;
     47         if(len <= 5) {
     48             if(len == 0)
     49                 n = 0;
     50             n = n * 10 + ch - '0';
     51             len++;
     52         }
     53     }
     54     int x;
     55     scanf("%d", &x);
     56     int temp = x;
     57     int a, b, c, d, e, k;
     58     scanf("%d%d%d%d%d%d", &a, &b, &c, &d, &e, &k);
     59     vec.push_back(x);
     60     vis[x] = true;
     61     for(int i = 1; i <= 4100; i++) {
     62         int x1 = 1ll * a * i * i % k * i * i % k;
     63         int x2 = 1ll * b * i * i % k * i % k;
     64         int x3 = 1ll * c * i * i % k;
     65         int x4 = 1ll * d * i;
     66         x = (x1 + x2 + x3 + x4 + e - 1) % k + 1;
     67         f[i] = x;
     68     }
     69     int all = 0;
     70     while(all < n) {
     71         all++;
     72         int now = f[temp];
     73         if(!vis[now]) {
     74             vis[now] = true;
     75             vec.push_back(now);
     76             temp = now;
     77         } else break;
     78     }
     79     int sz = vec.size();
     80     dp[0][0] = 1;
     81     int pre = 1, now = 0;
     82     for(int i = 1; i <= sz; i++) {
     83         swap(pre, now);
     84         int num = vec[i - 1];
     85         for(int j = 0; j < 8192; j++) dp[now][j] = dp[pre][j];
     86         for(int j = 0; j < 8192; j++) {
     87             dp[now][j ^ num] += dp[pre][j];
     88             if(dp[now][j ^ num] >= mod) dp[now][j ^ num] -= mod;
     89         }
     90     }
     91     ll sum = 0;
     92     for(int i = 1; i < 8192; i++) {
     93         sum += dp[now][i];
     94         if(sum >= mod) sum -= mod;
     95     }
     96     ll inv = pow_mod(2, sz);
     97     inv = pow_mod(inv, mod - 2);
     98     ans = ans * inv % mod;
     99     ans = ans * sum % mod;
    100     printf("%lld
    ", ans);
    101     return 0;
    102 }
  • 相关阅读:
    基于51单片机的独立按键和矩阵按键用法
    基于51单片机,蜂鸣器和led每秒1滴1亮的程序
    基于51单片机,3秒1亮的程序
    n个灯,隔m个依次点亮的具体情况方法
    单片机的定时器
    有关芯片的认识
    MATLAB变量
    二组玩法介绍
    tkinter的GUI界面
    magento 物流问题
  • 原文地址:https://www.cnblogs.com/scaulok/p/9573791.html
Copyright © 2011-2022 走看看