ZOJ 3265 Strange Game (最大匹配)

游戏开发与大数据分析的结合
本文探讨了游戏开发中如何应用大数据分析技术,通过案例分析展示了如何利用大数据提升游戏性能、优化玩家体验,并深入讨论了游戏数据的收集、处理与分析方法。
Strange Game

Time Limit: 3 Seconds      Memory Limit: 32768 KB

There is a strange game played on a special machine. The game has m prizes labeled from 0 to m-1. First, you are given n tickets, on which there is a number ai. For each time, you can put one ticket into the machine. By pressing the button on the machine you will get a number. You can press the button as many times as you like, but at least once. If you press k times, the number from the machine will be aik mod m, namely bi, and then you can take away the prize labeled bi as your trophy. Note that one ticket can only be used once, and same bi refers to same prize, which you can only take once.

Given nm and ai, you need to find the maximum number of different prizes you can get.

Input

The input contains no more than 30 cases. Each case has 2 lines. The first is two integers nm (0 ≤ n ≤ 200, 0 < m ≤ 109). The second line contains n integers a0a1, ..., an-1 (0 ≤ ai ≤ 109).

Proceed to the end of file.

Output

For each case output a integer, indicating the maximum number of different prizes you can get.

Sample Input

2 2
1 2

Sample Output

2

Author: LI, Cheng

Source: ZOJ Monthly, November 2009


这道题还是比较好的。很容易看出最大匹配的模型,但是如果把a[i]^k全部生成的话,右边的点数会太大,即使取模有循环节。如此,需要利用一个结论。如果一个a[i]的k次方,可以生成大于n种不同的数,这个时候就不用再继续生成了,因为n个匹配的点已经足够保证在不干扰其他点匹配的情况下,找到一种匹配方式。


#include<cstdio>
#include<map>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
#include<set>
#include<cmath>
using namespace std;
const int maxn = 1e5 + 5;
const int INF = 1e9;
const double eps = 1e-6;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> P;
#define fi first
#define se second

struct Edge {
  int from, to, cap, flow;
};

struct Dinic {
  int n, m, s, t;
  vector<Edge> edges;    // 边数的两倍
  vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
  bool vis[maxn];        // BFS使用
  int d[maxn];           // 从起点到i的距离
  int cur[maxn];         // 当前弧指针

  void ClearAll(int n) {
    for(int i = 0; i < n; i++) G[i].clear();
    edges.clear();
  }

  void ClearFlow() {
    for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
  }

  void AddEdge(int from, int to, int cap) {
    //cout << from << ' ' << to << ' ' << cap << endl;
    edges.push_back((Edge){from, to, cap, 0});
    edges.push_back((Edge){to, from, 0, 0});
    m = edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
  }

  bool BFS() {
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(s);
    vis[s] = 1;
    d[s] = 0;
    while(!Q.empty()) {
      int x = Q.front(); Q.pop();
      for(int i = 0; i < G[x].size(); i++) {
        Edge& e = edges[G[x][i]];
        if(!vis[e.to] && e.cap > e.flow) {
          vis[e.to] = 1;
          d[e.to] = d[x] + 1;
          Q.push(e.to);
        }
      }
    }
    return vis[t];
  }

  int DFS(int x, int a) {
    if(x == t || a == 0) return a;
    int flow = 0, f;
    for(int& i = cur[x]; i < G[x].size(); i++) {
      Edge& e = edges[G[x][i]];
      if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {
        e.flow += f;
        edges[G[x][i]^1].flow -= f;
        flow += f;
        a -= f;
        if(a == 0) break;
      }
    }
    return flow;
  }

  int Maxflow(int s, int t) {
    this->s = s; this->t = t;
    int flow = 0;
    while(BFS()) {
      memset(cur, 0, sizeof(cur));
      flow += DFS(s, INF);
    }
    return flow;
  }
};

Dinic g;
int a[maxn];
map<LL, int> M;

int main(){
    int n, m;
    while(scanf("%d%d", &n, &m) != EOF){
        for(int i = 1;i <= n;i++){
            cin >> a[i];
            a[i] %= m;
        }
        int source = 0, sink = n*n+1;
        g.ClearAll(n*n+5);
        for(int i = 1;i <= n;i++)
            g.AddEdge(source, i, 1);
        M.clear();
        int cnt = n+1;
        for(int i = 1;i <= n;i++){
            LL now = a[i];
            map<LL, int> vis;
            vis.clear();
            int num = 0;
            while(1){
                vis[now] = 1;
                if(M.count(now)==0){
                    g.AddEdge(cnt, sink, 1);
                    M[now] = cnt++;
                }
                g.AddEdge(i, M[now], 1);
                now = (now*a[i])%m;
                num++;
                if(num > n || vis.count(now))
                    break;
            }
        }
        cout << g.Maxflow(source, sink) << endl;
    }
    return 0;
}


随着信息技术在管理上越来越深入而广泛的应用,作为学校以及一些培训机构,都在用信息化战术来部署线上学习以及线上考试,可以与线下的考试有机的结合在一起,实现基于SSM的小码创客教育教学资源库的设计与实现在技术上已成熟。本文介绍了基于SSM的小码创客教育教学资源库的设计与实现的开发全过程。通过分析企业对于基于SSM的小码创客教育教学资源库的设计与实现的需求,创建了一个计算机管理基于SSM的小码创客教育教学资源库的设计与实现的方案。文章介绍了基于SSM的小码创客教育教学资源库的设计与实现的系统分析部分,包括可行性分析等,系统设计部分主要介绍了系统功能设计和数据库设计。 本基于SSM的小码创客教育教学资源库的设计与实现有管理员,校长,教师,学员四个角色。管理员可以管理校长,教师,学员等基本信息,校长角色除了校长管理之外,其他管理员可以操作的校长角色都可以操作。教师可以发布论坛,课件,视频,作业,学员可以查看和下载所有发布的信息,还可以上传作业。因而具有一定的实用性。 本站是一个B/S模式系统,采用Java的SSM框架作为开发技术,MYSQL数据库设计开发,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得基于SSM的小码创客教育教学资源库的设计与实现管理工作系统化、规范化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值