[数学 二分图匹配] SRM 456 div1 FunctionalEquation

本来想自己再推一下的,但是退役了也就弃坑了
未经允许的搬了搬题人的题解

这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述

// BEGIN CUT HERE  
#include<conio.h>
#include<sstream>
// END CUT HERE  
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<string>
#include<set>
#define pb push_back
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;

const int N=10005;
const int CC=16;

int n,C;
int x[N],y[N];
vector<int> v[(CC+5)<<1];

ll W[N]; int pnt=0;

inline ll calc(ll x){
  ll ret=0; for (int i=1;i<=pnt;i++) ret+=abs(W[i]-x); return ret;
}

ll w[CC+5][CC+5];
ll f[CC+5][1<<CC];

class FunctionalEquation{
public:
  long long minAbsSum(int C, int n, int x0, int xp, int xa, int xm, int y0, int yp, int ya, int ym){

    x[1]=x0; y[1]=y0; v[x[1]%(2*C)].pb(1);
    for (int i=2;i<=n;i++){
      x[i]=((ll)x[i-1]*xp+xa)%xm,y[i]=((ll)y[i-1]*yp+ya)%ym;
      v[x[i]%(2*C)].pb(i);
    }

    for (int x=0;x<C;x++)
      for (int y=0;y<C;y++){
    int a=x<<1,b=y<<1|1;
    pnt=0;
    for (int i:v[a])
      W[++pnt]=x+y+(::x[i]-a)-::y[i];
    for (int i:v[b])
      W[++pnt]=-x-y-(::x[i]-b)-C+::y[i];
    ll ret=1LL<<60;
    sort(W+1,W+pnt+1);
    int mid=(pnt+1)>>1,t=W[mid]/C;
    for (int i=t-5;i<=t+5;i++)
      ret=min(ret,calc((ll)i*C));
    w[x+1][y+1]=ret;
      }
    memset(f,0x3f,sizeof(f));
    f[0][0]=0;
    for (int i=0;i<C;i++)
      for (int s=0;s<(1<<C);s++)
    for (int j=1;j<=C;j++)
      if (~s>>(j-1)&1)
        f[i+1][s|(1<<(j-1))]=min(f[i+1][s|(1<<(j-1))],f[i][s]+w[i+1][j]);
    return f[C][(1<<C)-1];
  }


  // BEGIN CUT HERE
public:
  void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); }
private:
  template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
  void verify_case(int Case, const long long &Expected, const long long &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
  void test_case_0() { int Arg0 = 3; int Arg1 = 10; int Arg2 = 0; int Arg3 = 1; int Arg4 = 1; int Arg5 = 456; int Arg6 = 1; int Arg7 = 1; int Arg8 = 1; int Arg9 = 456; long long Arg10 = 0LL; verify_case(0, Arg10, minAbsSum(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)); }
  void test_case_1() { int Arg0 = 4; int Arg1 = 10; int Arg2 = 0; int Arg3 = 1; int Arg4 = 1; int Arg5 = 456; int Arg6 = 1; int Arg7 = 1; int Arg8 = 1; int Arg9 = 456; long long Arg10 = 5LL; verify_case(1, Arg10, minAbsSum(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)); }
  void test_case_2() { int Arg0 = 16; int Arg1 = 10000; int Arg2 = 654816386; int Arg3 = 163457813; int Arg4 = 165911619; int Arg5 = 987654321; int Arg6 = 817645381; int Arg7 = 871564816; int Arg8 = 614735118; int Arg9 = 876543210; long long Arg10 = 3150803357206LL; verify_case(2, Arg10, minAbsSum(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)); }

  // END CUT HERE

};

// BEGIN CUT HERE
int main(){
  FunctionalEquation ___test;
  ___test.run_test(-1);
  getch() ;
  return 0;
}
// END CUT HERE
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值