• gmoj 6832.world


    Description

    世界可以抽象成一个长度为偶数n 且元素互不相同的数列a。每当发生了一些意外,他都会相应的产生一些变化,并成为一个新的数列a′,并且它们满足以下关系:

    如果这个数列正好经过n 次变换后首次回到最初始的数列a ,这个世界便是幸运的。此时的幸运值是n;如果没有回到最初始的序列,幸运值便是0。
    那如果,这个序列的长度在[2,A] 之间的偶数内均匀随机时,请你告诉我,世界期望的幸运值是多少呢?

    Input

    输入一行一个正整数A,其意义见【题目描述】。

    Outout

    输出一行一个实数,表示我的幸运值的期望,请保留5 位小数。

    Solution

    对于第i个位置,经过k次变换后到达的位置应该是(i imes2^k \% (n+1))

    而对于第一个位置到达的的位置就是(2^k \%(n+1))

    所以回到第一个位置即(2^kequiv1(mod n+1))

    所以现在要求的是这个最小的k

    根据欧拉定理,(2^{phi(n+1)}equiv1(mod n+1))

    所以如果(phi(n+1)) 小于n,则n就不会是最小的k

    因为当n+1为质数是(phi(n+1)) 才会是n,所以当n+1为质数时才判断这个n

    但这个n不一定是最小的

    当n不是最小的时候,最小的一定是n的因数(讲真挺好证的,画个图,因为(y=2^x mod (n+1))这东西的y是循环的,所以要使刚好在n那等于1,则最小的那个数应该是n的因数)

    把n分解质因数,最多就8个数,所以时间复杂度(O(8n)) 可以接受

    Code

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #define N 10000001
    #define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    int i,j,cnt,tot,n,x,ma,prime[N],a[N],last[N];
    long long ans;
    bool bz[N];
    long long ksm(long long x,int y,int MO)
    {
        long long sum=1;
        while (y)
        {
            if (y&1)sum=sum*x%MO;
            x=x*x%MO;
            y>>=1;
        }
        return sum;
    }
    int main()
    {
        open("world");
        scanf("%d",&n);
        for (i=2;i<=n;i++)
        {
            if (!bz[i]) prime[++tot]=i;
            for (j=1;j<=tot;j++)
            {
                if (prime[j]*i>n) break;
                bz[prime[j]*i]=1;
                last[prime[j]*i]=prime[j];
                if (i%prime[j]==0) break;
            }
        }
        for (i=2;i<=n;i+=2)
        {
            if (bz[i+1]) continue;
            x=i;
            ma=0;
            if (ksm(2,i,i+1)==1) ma=i;
            while (last[x])
            {
                cnt=last[x];
                while (x%cnt==0) x/=cnt;
                if (ksm(2,i/cnt,i+1)==1) 
                {
                	ma=i/cnt;
                	break;
    			}
            }
            if (x>1) 
    		{
    			if (!ma) ma=i/x;else
    			if (ksm(2,i/x,i+1)==1 && ma==i) ma=i/x;
    		}
            if (ma==i) ans+=i;
        }
        printf("%.5Lf",ans/(long double)(n/2));
        return 0;
    }
    
    
    如果自己说什麽都做不到而什麽都不去做的话,那就更是什麽都做不到,什麽都不会改变,什麽都不会结束.
  • 相关阅读:
    Java静态分派与动态分派(二)
    重载和重写在jvm运行中的区别(一)
    startActivity启动过程分析(转)
    进程篇—进程整理(转)
    理解Android线程创建流程(转)
    Android进程绝杀技--forceStop(转)
    说说Android应用的persistent属性(转)
    Android四大组件与进程启动的关系(转)
    转: 安卓自动缩放布局,解决屏幕适配问题
    转: android apk 防止反编译技术(1~5连载)
  • 原文地址:https://www.cnblogs.com/Sport-river/p/13870813.html
Copyright © 2020-2023  润新知