zoukankan      html  css  js  c++  java
  • poj3708(公式化简+大数进制装换+线性同余方程组)

    刚看到这个题目,有点被吓到,毕竟自己这么弱。

    分析了很久,然后发现m,k都可以唯一的用d进制表示。也就是用一个ai,和很多个bi唯一构成。

    这点就是解题的关键了。 之后可以发现每次调用函数f(x),相当于a(ai),b(bi)了一下。这样根据置换的一定知识,一定会出现循环,而把循环的大小看成取模,把从m->k的看成余,于是可以建立一个线性同余方程。

    直接用模板解决之。。

    Recurrent Function
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 1102   Accepted: 294

    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:

    egin{tabular} {ll} 	extit{f}(	extit{j}) = 	extit{a}$_j$ & for 1$le$	extit{j}$<$	extit{d}, \ emph{f}(emph{d}$	imes$emph{n}+emph{j}) = d$	imes$f(	extit{n})+	extit{b}$_j$ & for 0$le$	extit{j}$<$	extit{d} and 	extit{n}$ge$1, \ end{tabular}

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

    egin{tabular}{l}emph{f}$_x$(emph{m}) = emph{f}(emph{f}(emph{f}($cdots$emph{f}(emph{m})))) quademph{x} times \ end{tabular}

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

    egin{tabular}{l}emph{f}$_x$(emph{m}) = emph{k}\ end{tabular}

    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
    //
    //  main.cpp
    //  poj3708
    //
    //  Created by 陈加寿 on 15/11/28.
    //  Copyright (c) 2015年 陈加寿. All rights reserved.
    //
    
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    
    
    int a[110],b[110];
    char strm[110],strk[110];
    int m[110],k[110];
    int savem[1100],savek[1100];
    int cntm,cntk;
    
    void Tentod(int ten[],int len,int &cnt,int d,int save[])
    {
        int tcnt=0;
        while(ten[tcnt]==0) tcnt++;
        cnt=0;
        while(tcnt<len)
        {
            for(int i=tcnt;i<len;i++)
            {
                ten[i+1] += (ten[i]%d)*10;
                ten[i] /= d;
            }
            save[cnt++] = ten[len]/10;
            ten[len]=0;
            while(tcnt<len&&ten[tcnt]==0) tcnt++;
        }
        /*
        for(int i=0;i<cnt;i++)
            printf("%d ",save[i]);
        printf("
    ");
        */
    }
    
    
    
    /*对于x=r0(mod m0)
     x=r1(mod m1)
     ...
     x=rn(mod mn)
     输入数组m和数组r,返回[0,[m0,m1,...,mn]-1] 范围内满足以上等式的x0。
     x的所有解为:x0+z*[m0,m1,...mn](z为整数)
     */
    long long cal_axb(long long a,long long b,long long mod)
    {
        //防乘法溢出
        long long sum=0;
        while(b)
        {
            if(b&1) sum=(sum+a)%mod;
            b>>=1;
            a=(a+a)%mod;
        }
        return sum;
    }
    
    //ax + by = gcd(a,b)
    //传入固定值a,b.放回 d=gcd(a,b), x , y
    void extendgcd(long long a,long long b,long long &d,long long &x,long long &y)
    {
        if(b==0){d=a;x=1;y=0;return;}
        extendgcd(b,a%b,d,y,x);
        y -= x*(a/b);
    }
    
    long long Multi_ModX(long long m[],long long r[],int n)
    {
        long long m0,r0;
        m0=m[0]; r0=r[0];
        for(int i=1;i<n;i++)
        {
            long long m1=m[i],r1=r[i];
            long long k0,k1;
            long long tmpd;
            extendgcd(m0,m1,tmpd,k0,k1);
            if( (r1 - r0)%tmpd!=0 ) return -1;
            k0 *= (r1-r0)/tmpd;
            m1 *= m0/tmpd;
            r0 = ( cal_axb(k0,m0,m1)+r0)%m1;
            m0=m1;
        }
        return (r0%m0+m0)%m0;
    }
    
    int main(int argc, const char * argv[]) {
        int d;
        while(cin>>d)
        {
            if(d==-1) break;
            for(int i=1;i<d;i++) cin>>a[i];
            for(int i=0;i<d;i++) cin>>b[i];
            scanf("%s",strm);
            scanf("%s",strk);
            int len = strlen(strm);
            for(int i=0;i<len;i++)
                m[i] = strm[i]-'0';
            Tentod(m,len,cntm,d,savem);
            len = strlen(strk);
            for(int i=0;i<len;i++)
                k[i] = strk[i]-'0';
            Tentod(k, len, cntk, d, savek);
            // 这样就得到了。a,b。。。
            // 然后构建同模方程
            if(cntm != cntk)
            {
                printf("NO
    ");
            }
            else
            {
                int flag=0;
                long long m[1010],r[1010];
                for(int i=0;i<cntm-1;i++)
                {
                    int a1=savem[i],a2=savek[i];
                    int tm=1;
                    int ta=a1;
                    while(b[ta]!=a1)
                    {
                        tm++;
                        ta=b[ta];
                    }
                    ta=a1;
                    int tr=0;
                    while(ta != a2)
                    {
                        tr++;
                        ta=b[ta];
                        if(ta==a1)
                        {
                            flag=1;
                            break;
                        }
                    }
                    m[i]=tm;
                    r[i]=tr;
                    if(flag==1) break;
                }//这里面都是b
                int a1=savem[cntm-1],a2=savek[cntm-1];
                int tm=1;
                int ta=a1;
                while(a[ta]!=a1)
                {
                    tm++;
                    ta=a[ta];
                }
                ta=a1;
                int tr=0;
                while(ta != a2)
                {
                    tr++;
                    ta=a[ta];
                    if(ta==a1)
                    {
                        flag=1;
                        break;
                    }
                }
                m[cntm-1]=tm;
                r[cntm-1]=tr;
                if(flag == 1)
                {
                    printf("NO
    ");
                }
                else
                {
                    long long ans=Multi_ModX(m, r,cntm);
                    if(ans==-1) printf("NO
    ");
                    else cout<<ans<<endl;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Java反射机制DOME
    Contos7 装bcm4312无线网卡驱动
    windows8.1+centos7双系统(装完centos后无win8引导)
    request+response
    HTTP协议+servlet配置
    类加载和反射
    线程池+线程安全
    IO流之Properties(String键值对)+序列流+打印流+commons-IO(最终流程)
    IO流之字节流 +字符流 (复制文件)
    IO流
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5002859.html
Copyright © 2011-2022 走看看