[数学][中国剩余定理]Leapfrog

题目描述

Somewhere in an animal kingdom far from here there is a large forest. Inside the forest live a large number of frogs.
Every year the frogs gather along the big central road in the forest to show the other animals their unique ability
during the Big Animal Prowess Conference (BAPC).
These frogs are experts in forming towers by climbing on top of each other. They are, however, not experts in gathering orderly on the road, so the frogs have arrived on different positions along the central road. The frogs are also notorious show offs: their every jump is as far as they can and always a prime distance. Not every frog is as strong as the others, so jumping distances may vary. Naturally, the frogs only jump to increase their position, never the other way!
The frog king wants to invite all visitors of the BAPC to marvel at the most spectacular frog tower. Multiple frog towers can be created, but the king wants to show the largest tower at the smallest possible position. He doesn’t want anyone to miss the action because they were at the wrong spot! Can you help the frog king determine the position and size of the tower?

输入

• On the first line one integer n, the number of frogs gathering on the central road, with 1 ≤ n ≤ 40.
• Then follow n lines with integers xi and di, the initial position and prime jumping distance of the ith frog. Here 0 ≤ xi ≤ 260 and 2 ≤ di ≤ 108
. It is given that the product of all unique jumping distances is less than 109.

输出

Output a single line with two integers indicating:
• the smallest position of the highest frog tower,
• the size of the highest frog tower.
Separate these integers by a space.

样例输入

3
0 2
1 2
3 3

样例输出

3 2
思路:很快想到CRT,但有几个地方要小心:1.余数a=aa(起始位置)%p(模数);2.p相同但a不同的青蛙不可能跳到同一点,p相同且a相同的青蛙可能有多只;3.CRT算出同余方程组的解后,要判定解是否合法,即解是否大于所选青蛙的起始位置(aa)
AC代码://写的非常极其乱
#include <iostream>
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
typedef long long ll;
using namespace std;

struct Node{ll si,ssi,num;};bool cmp(Node a,Node b){return a.si<b.si;};
ll ss[45],dis[45],s[45];
map<ll,ll> mp;
map<ll,ll> mp_;
ll cnt=0;
vector<Node> remain[45];
ll ans=9223372036854775807,sum=0,sum_=0;
ll p[45],a[45],aa[45];

void exgcd(ll a,ll b,ll& d,ll& x,ll& y){
    if(!b){ d=a; x=1; y=0;}
    else{ exgcd(b,a%b,d,y,x); y-=x*(a/b); }
}
ll CRT(){
    ll P=p[1],A=a[1],t;
    for(ll i=2;i<=cnt;i++){
        ll d,x,y;
        exgcd(P,p[i],d,x,y);
        if((a[i]-A)%d) return -1;
        x*=(a[i]-A)/d,t=p[i]/d,x=(x%t+t)%t;
        A=P*x+A,P=P/d*p[i],A%=P;
    }
    A=(A%P+P)%P;
    for(ll i=1;i<=cnt;i++){//重点3
        if(A<aa[i]) A+=(aa[i]-A)/P*P;
        while(A<aa[i]) A+=P;
    }
    return A;
}

void dfs(ll x){
  if(x==0){
    ll tmp=CRT();
    //重点4
    if(sum>sum_) {sum_=sum,ans=tmp;}
    if(sum==sum_&&tmp<ans) ans=tmp;
    return;
  }
  for(ll i=0;i<(ll)remain[x].size();i++){
    a[x]=remain[x][i].si;p[x]=mp_[x];
    aa[x]=remain[x][i].ssi;
    sum+=remain[x][i].num;
    dfs(x-1);
    sum-=remain[x][i].num;
  }
}

int main()
{
    ll n;scanf("%lld",&n);
    for(ll i=1;i<=n;i++){
        scanf("%lld%lld",&ss[i],&dis[i]),s[i]=ss[i]%dis[i];//重点1
        if(!mp[dis[i]]){
            mp[dis[i]]=++cnt;
            mp_[cnt]=dis[i];
        }
        remain[mp[dis[i]]].push_back(Node{s[i],ss[i],1});
    }
    for(ll i=1;i<=cnt;i++){//重点2
        sort(remain[i].begin(),remain[i].end(),cmp);
        for(ll j=1;j<(ll)remain[i].size();j++){
            if(remain[i][j].si==remain[i][j-1].si) remain[i][j].num+=remain[i][j-1].num;
        }
    }
    dfs(cnt);
    printf("%lld %lld
",ans,sum_);
    return 0;
}

转载请注明出处:https://www.cnblogs.com/lllxq/
原文地址:https://www.cnblogs.com/lllxq/p/9536517.html