poj 3708 Recurrent Function

Recurrent Function

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 1233   Accepted: 336

Description

Dr. Yao is involved in a secret research on the topic of the properties of recurrent function. Some of the functions in this research are in the following pattern:

in which set {ai} = {1, 2, …, d-1} and {bi} = {0, 1, …, d-1}.
We denote:

Yao‘s question is that, given two positive integer m and k, could you find a minimal non-negative integer x that

Input

There are several test cases. The first line of each test case contains an integer d (2≤d≤100). The second line contains 2d-1 integers: a1, …, ad-1, followed by b0, ..., bd-1. The third line contains integer m (0<m≤10100), and the forth line contains integer k (0<k≤10100). The input file ends with integer -1.

Output

For each test case if it exists such an integer x, output the minimal one. We guarantee the answer is less than 263. Otherwise output a word "NO".

Sample Input

2
1
1 0
4
7
2
1
0 1
100
200
-1

Sample Output

1
NO

Hint

For the first sample case, we can see that f(4)=7. And for the second one, the function is f(i)=i.

题意:求解递归方程,该类方程在具体数学第一章中有明确介绍,这里只给结论,若要求解f(x),可以先将x转化成c进制c进制一共m位,即(xmxm-1...x1x0)c,那么有结论:

f((xmxm-1...x1x0)c)=(axmbxm-1bxm-2...bx1bx0)c

思路:结论已介绍,可以看出将x化成c进制后每一位都在进行置换操作,c进制首位用ai来置换,后面几位都用bi来置换。那么如果将k也转化成d进制,那么如果m的d进制的每一位通过不断置换之后最终与k的每一位分别相等,置换的最小次数x就是所求。

我们设最少置换x次,m的d进制的每一位各自置换到k的每一位需要ci次,并且每一位置换足够次数会产生轮回,轮回的大小记为loop(i)

那么x满足条件:

x==c1 mod(loop(1))

x==c2 mod(loop(2))

.....

x==cn mod(loop(n))

这样就是求满足上述模方程组的最小解即可。

AC代码:

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>
#include<string>
#include<queue>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
const int N_MAX = 10+500;
typedef long long ll;
// 大数类
class bign
{
#define  base  1000
#define  digit  3
private:
    int _arr[110];
    int _m;
    void bign::_simplify(void)
    {
        for (int i = 0; i <= _m; i++)
        {
            if (i == _m && _arr[i] >= base) _m++;
            _arr[i + 1] += _arr[i] / base;
            _arr[i] %= base;
        }
    }
public:
    bign::bign(void) : _m(0) { memset(_arr, 0, sizeof(_arr)); }
    bign::bign(int init) : _m(0)
    {
        memset(_arr, 0, sizeof(_arr));
        _arr[0] = init;
        _simplify();
    }
    friend istream& operator >> (istream& fin, bign& a)
    {
        char init[10010]; int len, b, t;
        fin >> init;
        len = strlen(init); a._m = -1;
        for (int i = len - 1; i >= 0;)
        {
            t = 0, b = 1;
            for (int j = 0; j < digit && i >= 0; j++, i--)
            {
                t += (init[i] - ‘0‘) * b;
                b *= 10;
            }
            a._arr[++a._m] = t;
        }
        return fin;
    }
    friend bign operator / (bign a, int b)
    {
        for (int i = a._m; i >= 0; i--)
        {
            if (a._arr[i] < b && i == a._m && i != 0) a._m--;
            if (i > 0) a._arr[i - 1] += (a._arr[i] % b) * base;
            a._arr[i] /= b;
        } return a;
    }
    friend int operator % (bign a, int b)
    {
        for (int i = a._m; i >= 0; i--)
        {
            if (i == 0) return a._arr[i] % b;
            else a._arr[i - 1] += (a._arr[i] % b) * base;
        }
    }
    friend bool operator == (bign a, bign b)
    {
        if (a._m != b._m) return false;
        for (int i = 0; i <= a._m; i++)
            if (a._arr[i] != b._arr[i]) return false;
        return true;
    }
};

pair<ll,ll> trans(ll *a,ll m,ll k ) {//采用a置换,m为需要置换的数,k为m置换的终点,返回循环次和圈的大小
    ll num = 0;//num为从m到k的循环次数,不存在则为-1
    ll tmp = m;
    while (tmp!=k) {
        if (num != 0 && tmp == m) { num = -1; break; }
        num++;
        tmp = a[tmp];
    }
    if (num == -1)return make_pair(-1, 0);
    int loop = 0;
    while (1) {
        if (loop != 0 && tmp == k) { break; }
        loop++;
        tmp = a[tmp];
    }
    return make_pair(num,loop);
}

ll gcd(ll a,ll b) {
    if (b == 0)return a;
    return gcd(b, a%b);
}

ll extgcd(ll a,ll b,ll &x,ll &y) {
    if (b == 0) {
        x = 1; y = 0;
        return a;
    }
    ll ans = extgcd(b,a%b,x,y);
    ll tmp = x;
    x = y;
    y = tmp - a / b*y;
    return ans;
}
ll mod_inverse(ll a,ll m) {
    ll x, y;
    extgcd(a,m,x,y);
    return (m + x%m) % m;
}

pair<ll, ll>linear_congruence(const ll *A,const ll *B,const ll*M,const int& num) {
    ll x = 0,m = 1;
    for (int i = 0; i < num;i++) {
        ll a = A[i] * m, b = B[i] - A[i] * x, d = gcd(M[i], a);
        if (b%d != 0)return make_pair(0, -1);
        ll t = b / d*mod_inverse(a / d, M[i] / d) % (M[i] / d);
        x = x + m*t;
        m *= M[i] / d;
    }
    return make_pair((x%m+m)%m, m);
}

ll d;
ll a[N_MAX], b[N_MAX];
bign k, m;
ll kd[N_MAX], md[N_MAX];//存储k和m的D进制形式
ll A[N_MAX], B[N_MAX], M[N_MAX];
int main() {
    while(scanf("%lld",&d)&&d!=-1) {
        for (int i = 1; i < d;i++)scanf("%lld",&a[i]);
        for (int i = 0; i < d;i++)scanf("%lld",&b[i]);
        cin >> m >> k;
        int num = 0;
        while (!(m==0)) {
            md[num++] = m%d;
            m =m/ d;
        }
        int num2 = 0;
        while (!(k == 0)) {
            kd[num2++] = k%d;
            k = k / d;
        }
        if (num != num2) { puts("NO"); continue; }
        pair<ll, ll>P;
        bool flag = 0;
        for (int i = 0; i < num-1;i++) {
            P = trans(b,md[i],kd[i]);
            if (P.first == -1) { puts("NO"); flag = 1; break; }
            A[i] = 1, B[i] = P.first, M[i] = P.second;
        }
        if (flag)continue;

        P = trans(a, md[num - 1], kd[num - 1]);
        if (P.first == -1) { puts("NO"); continue; }
        A[num - 1] = 1, B[num - 1] = P.first, M[num - 1] = P.second;
        P = linear_congruence(A,B,M,num);
       if(P.second==-1) { puts("NO"); continue; }
       else printf("%lld\n",P.first);
    }
    return 0;
}

时间: 2024-10-10 11:02:17

poj 3708 Recurrent Function的相关文章

数学推导+高精度进制转换+解同余方程 POJ 3708

题意:点击打开链接 把m,k表示成d进制,对于这个递归函数,每一次递归都是一次每一位数字的置换,求出每一位的循环节,最终f(m)=k就是要每一位都相等,即解同余方程组. 代码: #include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include<climits> #include <algorith

POJ3708 Recurrent Function

[题意] 给出一个正整数d(2<=d<=100):一个元素个数为d-1的集合a,每个集合元素ai对应一个1~d-1的整数:以及定义相同的大小为d集合bi. f函数的定义原题已给出.求数m最少经过多少次函数操作变为数k,无解输出NO. [题解] 我们可发现当x>=d时,f(x)=d*f(x/d)+b[x mod d],x<d时,f(x)=a[x]. 不难发现其实这就是在x的d进制下,对每一位进行变换,某一位如果是x,要么变a[x],要么变b[x].所以答案就是当某一次操作后,每一位都

[转] POJ数学问题

转自:http://blog.sina.com.cn/s/blog_6635898a0100magq.html 1.burnside定理,polya计数法 这个大家可以看brudildi的<组合数学>,那本书的这一章写的很详细也很容易理解.最好能完全看懂了,理解了再去做题,不要只记个公式. *简单题:(直接用套公式就可以了) pku2409 Let it Bead      http://acm.pku.edu.cn/JudgeOnline/problem?id=2409 pku2154 Co

POJ【数论/组合/博弈论】

 POJ[数论/组合/博弈论]题目列表 POJ[数论/组合/博弈论]题目列表 原来的列表比较水,今天换了一个难一些的列表,重新开始做~ 红色的代表已经AC过,蓝色的代表做了但是还没过.这句话貌似在我空间里的每份列表里都有额. 博弈论 POJ 2234 Matches Game POJ 2975 Nim POJ 2505 A multiplication game POJ 1067 取石子游戏 POJ 2484 A Funny Game POJ 2425 A Chess Game POJ 29

poj数论(转)

1.burnside定理,polya计数法    这个大家可以看brudildi的<组合数学>,那本书的这一章写的很详细也很容易理解.最好能完全看懂了,理解了再去做题,不要只记个公式.    *简单题:(直接用套公式就可以了)    pku2409 Let it Bead       pku2154 Color    pku1286 Necklace of Beads    *强烈推荐:(这题很不错哦,很巧妙)    pku2888 Magic Bracelet2.置换,置换的运算 置换的概念

『转』数学专辑

1.burnside定理,polya计数法 这个大家可以看brudildi的<组合数学>,那本书的这一章写的很详细也很容易理解.最好能完全看懂了,理解了再去做题,不要只记个公式. *简单题:(直接用套公式就可以了) pku2409 Let it Bead   http://acm.pku.edu.cn/JudgeOnline/problem?id=2409 pku2154 Color http://acm.pku.edu.cn/JudgeOnline/problem?id=2154 pku12

ACM数学(转)

从放暑假前周sir给我讲了一个用polya计数法和burnside定理做的题目(pku2409)后,突然觉得组合数学挺有意思,然后从那时起到现在几乎都在做这类的题目. 做到现在感觉这类题目的一些基本知识点都差不多有所了解了,水题也刷了不少,但还有很多难题自己实在是做不动,所以准备把这类题目先放一放,然后把前段时间做的水题整理一下(供以后的初学者参考,大牛就不要看了哈,都是水题).剩下的比较难的题目就慢慢来吧,以后做出来再不上,这个小结会不断地更新.也希望大家有好的题目可以推荐一下,分享一下哈.

数论专题(转)

经过长时间的试验,发现果然学编程还是要学好数学先,数学引发的更加有质的变化,而盲目学各种编程语言也不能获得一种不一样的体验,或者我没掌握到诀窍.另外打算从这学期学的 信安数学基础 学到的庞大的数论体系开刀,上了这课明显体会到彻底自学就是扯蛋. 网上找到这份题目,还不错的赶脚,刷起! 2014-11-11开始刷起,有链接表示KO 博弈论POJ 2234 Matches GamePOJ 2975 NimPOJ 2505 A multiplication gamePOJ 1067 取石子游戏POJ 2

(转) Written Memories: Understanding, Deriving and Extending the LSTM

R2RT Written Memories: Understanding, Deriving and Extending the LSTM Tue 26 July 2016 When I was first introduced to Long Short-Term Memory networks (LSTMs), it was hard to look past their complexity. I didn’t understand why they were designed they