• HGOI20181029模拟题解


    HGOI20181029模拟题解

    /*
    sxn让我一定要谴责一下出题人和他的数据!
    */

    problem:

    给出十进制数a,b,然后令(R)10=(a)10*(b)10,给出c表示一个k进制数(1<k<=16)问(R)k=(c)k在k等于多少时成立,求k的最小值

    如果无解输出0.

    sol:显然a,b比较大的时候a*b一定爆longlong,考虑一个问题,显然若a*b>1e18那么c一定不可能等于R,一定小于等于R(主要是由于给出的c不含有字母)

    然后弄个stack来求一下a*b转k进制,暴力枚举k即可,复杂度O(k*T*w)其中w是常数w=位数约等于18

    code:

    # include <bits/stdc++.h>
    #ifdef LOCAL-ljc 
    #pragma GCC optimze(2)
    #endif
    # define int long long
    using namespace std;
    const int MAXN=75;
    char s[MAXN];
    inline int read()
    {
        int X=0,w=0; char c=0;
        while (!(c>='0'&&c<='9')) w|=c=='-',c=getchar();
        while (c>='0'&&c<='9') X=(X<<1)+(X<<3)+(c^48),c=getchar();
        return w?-X:X; 
    }
    inline void print(int x)
    {
        if (x<0){ putchar('-');x=-x;}
        if (x>9) print(x/10);
        putchar('0'+x%10);
    }
    char val(int x)
    {
        if (x>=0&&x<=9) return x+'0';
        else return x-10+'A';
    }
    bool cmp(char *s1,char *s2,int len)
    {
        for (int i=0;i<len;i++)
         if (s1[i]!=s2[i]) return false;
        return true;
    }
    bool check(int x,int Base)
    { 
        char E[MAXN]; stack<int>st; 
        int rec=x;
        while (x) { st.push(x%Base); x/=Base;}
        int len=0;
        while(!st.empty()) { E[len++]=val(st.top());st.pop();}
        if (cmp(E,s,len)) return 1;
        else return 0; 
    }
    signed main()
    {
        #ifdef LOCAL-ljc
            freopen("input.in","r",stdin);
            freopen("output.out","w",stdout);
        #else 
            freopen("base.in","r",stdin);
            freopen("base.out","w",stdout);
        #endif 
        int T=read();
        while (T--) {
            int p=read(),q=read(); int R=p*q;
            if ( p> (int) (1e18) / q) {
                print(0),putchar('
    ');
                continue;
            }
            cin>>s;
            bool f=false; 
            for (int i=2;i<=16;i++) 
                if (check(R,i)) { print(i); putchar('
    '); f=true; break;}  
            if (!f) { putchar('0');putchar('
    ');}    
        }
        return 0;
    }

    problem:给出置换关系a[]*p[]=c[] ,其中c_(p_i)=a_i,问一个有序排列[1,2,3,....n]通过最少k(k>0)次和P数组置换可以重新变成有序排列[1,2,3...n]

    sol:发现置换,然后想到置换环,然后经过一次置换以后所有置换环,均向同一方向旋转一次,然后问你多少次置换重新变成有序,就是求置换环大小的lcm

    按照样例来说:

    5
    3 4 1 5 2

    其中:置换环有2个 分别是[1,3] [2,4,5]这里[]中的数组下标,然后可以发现长度是(2,3),答案就是lcm(2,3)=6

    我们可以O(n)找出所有置换环,问题是求出lcm(o1,o2...ok)

    显然如果输入比较大的时候lcm容易爆longlong,然后我们可以gaojing大法?

    不行,不能打高精度!(看到模数)

    lcm就是最小公倍数,那么对每一个数进行质因数分解

    ai=Piki   然后lcm{ai}=Pimax(ki)

    打质因数分解23333

    我怕爆掉然后就打了两个算法。。

    # include <bits/stdc++.h>
    #ifdef LOCAL-ljc
    #pragma GCC optimze(2)
    #endif
    # define int long long
    using namespace std;
    const int MAXN=1e5+10;
    const int mo=19184192;
    bool vis[MAXN];
    int n,p[MAXN],ans,o[MAXN];
    int max_Num;
    inline int read()
    {
        int X=0,w=0; char c=0;
        while (!(c>='0'&&c<='9')) w|=c=='-',c=getchar();
        while (c>='0'&&c<='9') X=(X<<1)+(X<<3)+(c^48),c=getchar();
        return w?-X:X; 
    }
    inline void print(int x)
    {
        if (x<0){ putchar('-');x=-x;}
        if (x>9) print(x/10);
        putchar('0'+x%10);
    }
    int gcd(int a,int b)
    {
        if (b==0) return a;
        else return gcd(b,a%b);
    } 
    int lcm(int a,int b){return a*b/gcd(a,b);}
    
    void dfs(int u)
    {
        ans++; vis[u]=true;
        if (vis[p[u]]==true) return;
        else dfs(p[u]);
    }
    
    vector<int>P;
    bool prime[MAXN];
    int a[MAXN];
    
    void getprime(int MAXN)
    {
        memset(prime,true,sizeof(prime));
        P.clear(); prime[0]=prime[1]=false;
        for (int i=2;i<=MAXN;i++) {
            if (!prime[i]) continue; P.push_back(i);
            if (i+i>MAXN) continue;
            for (int j=i+i;j<=MAXN;j+=i) prime[j]=false;
        } 
    }
    void in(int num)
    {
        for (int i=0;i<P.size();i++) {
            int tmp=0; 
            while (num%P[i]==0) tmp++,num/=P[i];
            a[P[i]]=max(a[P[i]],tmp);    
        } 
         
    }
    int pow(int x,int n,int mo)
    {
        if (n==0) return 1;
        int t=pow(x,n/2,mo)%mo;
        t=t*t%mo;
        if (n%2==1) t=t*x%mo;
        return t%mo;
    }
    int getlcm()
    {
        memset(a,0,sizeof(a));
        for (int i=1;i<=o[0];i++) {
            int num=o[i]; in(num);
        }
        int ret=1;
        for (int i=0;i<P.size();i++)
         if (a[P[i]]!=0) ret=ret*pow(P[i],a[P[i]],mo)%mo;
        return ret; 
    }
    signed main()
    {
        #ifdef LOCAL-ljc
            freopen("perm.in","r",stdin);
        #else
            freopen("perm.in","r",stdin);
            freopen("perm.out","w",stdout);
        #endif
        n=read();
        for (int i=1;i<=n;i++) p[i]=read();
        memset(vis,false,sizeof(vis));
        for (int i=1;i<=n;i++) {
            if (vis[i]) continue;
            ans=0;
            if (vis[i]==false) dfs(i);
            o[++o[0]]=ans; 
        }
        bool flag=true;
        ans=1;
        for (int i=1;i<=o[0];i++) {
            ans=lcm(ans,o[i]);
            if (ans<0) flag=false;
        }
        if (flag) { print(ans%mo);putchar('
    '); return 0;}
        ans=1;
        max_Num=0;
        for (int i=1;i<=o[0];i++) max_Num=max(max_Num,o[i]);
        getprime(max_Num);
        print(getlcm()); 
        putchar('
    ');
        return 0;
    }

    problom:算n个数都是n的二十四点

    sol:打表+找规律,

    若n>=12,有这样的规律,

    如果n是奇数,那么可以分解为(3n)/n * (8n)/n +n-n+n-n...显然前面用掉的是(3+1+8+1=13)后面的+n-n...一定是偶数,所以可以消为0)

    如果n是偶数,那么可以分解成(4n/n)*(6n)/n+n-n+n-n...显然前面用掉的是(4+1+6+1=12)后面+n-n...一定是偶数,所以可以消掉为0)

    否则n<=12暴力打表算。

    code:

    # include <bits/stdc++.h> 
    using namespace std;  
    int main()  
    {  
    //    freopen("card.in","r",stdin);
    //    freopen("card.out","w",stdout);
        int n,tmp, T; 
        scanf ("%d", &T);
        for (int t = 1; t <= T; ++ t){  
            scanf ("%d", &n);
            switch (n) {
                case 1:printf("-1
    ");break;
                case 2:printf("-1
    ");break;
                case 3:printf("-1
    ");break;
                case 4:printf("1 * 2
    5 + 3
    6 + 4
    ");  break;
                case 5:printf("1 * 2
    3 / 6
    4 - 7
    5 * 8
    "); break;
                case 6:printf("1 + 2
    3 + 4
    5 - 6
    7 + 8
    10 - 9
    ");  break;
                case 7:printf("1 + 2
    3 + 8
    9 / 4
    10 + 5
    11 + 6
    12 + 7
    "); break;
                case 8:printf("1 + 2
    3 + 9
    4 - 5
    11 * 6
    12 * 7
    13 * 8
    10 + 14
    ");break;
                case 9:printf("1 + 2
    3 + 10
    4 / 5
    6 / 7
    8 / 9
    11 - 12
    15 - 13
     16 - 14
    ");  break;
                case 10:printf("1 + 2
    3 / 4
    5 / 6
    7 / 8
    9 / 10
    11 + 12
    16 + 13
    17 + 14
    18 + 15
    ");break;
                case 11:printf("1 + 2
    3 / 4
    5 / 6
    7 - 8
    15 * 9
    16 * 10
    17 * 11
    12 + 13
    19 + 14
    20 + 18
    ");  break;
                case 12:printf("1 + 2
    3 - 4
    5 * 14
    6 * 15
    7 * 16
    8 * 17
    9 * 18
    10 * 19
    11 * 20
    12 * 21
    13 + 22
    ");  break;
                case 13:printf("1 + 2
    3 / 4
    5 / 6
    7 - 8
    17 * 9
    18 * 10
    19 * 11
    20 * 12
    21 * 13
    22 + 14
    23 - 15
    24 - 16
    "); break;
                default: {
                    printf("1 + 2
    3 + 4
    5 + 6
    7 + 8
    9 + 10
    ");  
                    printf("%d + %d
    %d + %d
    %d + %d
    ",n+1,n+2,n+3,n+4,n+5,n+6);  
                    printf("%d / 11
    %d / 12
    ",n+7,n+8);  
                    printf("%d * %d
    ",n+9,n+10);  
                    printf("13 - 14
    ");  
                    tmp=n-14;  
                    int i;  
                    for(i=0;i<tmp;i++) printf("%d * %d
    ",n+12+i,15+i);  
                    printf("%d + %d
    ",n+11,n+12+tmp);  
                    }  
                    break;
                }
        }  
        return 0;  
    }  
  • 相关阅读:
    Lambda表达式
    工具类:mybatis中使用Threadlocal开启session及关闭session
    构造函数
    window phone ListBox多选
    ZOJ 3681 ZJU2013年01月月赛F题 E Cup 2
    2012百度之星冬季赛第四场第二题 度熊的复仇
    HDU 4476 HDOJ Cut the rope
    HDU 4475 HDOJ Downward paths
    2012百度之星冬季赛第二场第二题 消去游戏I
    ZOJ 3684 ZJU2013年01月月赛I题 Destroy
  • 原文地址:https://www.cnblogs.com/ljc20020730/p/9870273.html
Copyright © 2020-2023  润新知