zoukankan      html  css  js  c++  java
  • [gym102511K]Traffic Blights

    为了方便,对于集合$S$,称$kequiv S(mod M)$当且仅当存在$xin S$使得$kequiv x(mod M)$

    枚举红绿灯,对每一个点即限制$k$对$g_{i}+r_{i}$取模后的结果,同时相邻两个红绿灯限制相差是$o(1)$的,即可以提取出以下这个模型——

    $n$次操作,每次操作给定$M$和$Ssubseteq [0,M)$,新增限制$k otequiv S(mod M)$

    每次操作后,求随机整数$k$满足当前所有限制的概率

    数据范围为$1le nle 500$,$1le Mle 100$

    令$X=2^{3} imes 3^{2} imes 5 imes 7$,那么$forall 1le Mle 100,frac{M}{gcd(M,X)}$为一个素数的幂次或1

    枚举随机整数$k$对$X$取模的余数$a$($0le a<X$),求出在满足给定限制下还满足$kequiv a(mod X)$的概率,将这些概率累加即为答案

    令$k=a+tX$,问题即变为对于随机整数$t$,$a+tX$满足所有限制的概率,代入后限制$k otequiv S(mod M)$即可转换为$frac{X}{g}t otequiv S'(mod frac{M}{g})$

    (其中$g=gcd(M,X)$,$S'={frac{x}{g}mid (gmid x)and (x+aequiv S(mod M))}$)

    由于$gcd(frac{M}{g},frac{X}{g})=1$,再令$S'$所有元素乘上$frac{X}{g}$在模$frac{M}{g}$意义下的逆元,即$t otequiv S'(mod frac{M}{g})$

    根据$X$的性质,$frac{M}{g}$必然是素数的幂次或1,假设是$p$的幂次,不妨转换为$p^{lfloorlog_{p}100 floor-ord_{p}(X)}$,此时相同素数的幂次必然都相同,直接对$S'$求并即可

    (从同余的角度更容易理解此过程,但不同余方便实现)

    最终,模数两两互素,每一个概率相乘即为答案

    时间复杂度每一次都需要$o(MX)$去转化这个限制,总复杂度即$o(nMX)$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 105
     4 #define X 2520
     5 struct del{
     6     int i,P,x;
     7 };
     8 vector<int>v;
     9 vector<del>v_del;
    10 int    n,x,r,g,p[N],visp[N],phi[N],tot[X][N],vis[X][N][N];
    11 double ans;
    12 int gcd(int x,int y){
    13     if (!y)return x;
    14     return gcd(y,x%y);
    15 }
    16 int pow(int n,int m,int mod){
    17     int s=n,ans=1;
    18     while (m){
    19         if (m&1)ans=ans*s%mod;
    20         s=s*s%mod;
    21         m>>=1;
    22     }
    23     return ans;
    24 }
    25 void add(int p,int m,vector<int>v){
    26     int g=gcd(m,X),mm=m/g,P=mm,inv=pow(X/g,phi[mm]-1,mm);
    27     if (P%2==0)P=8;
    28     if (P%3==0)P=9;
    29     for(int i=0;i<X;i++)
    30         for(int j=0;j<v.size();j++){
    31             int x=(v[j]-i%m+m)%m;
    32             if (x%g)continue;
    33             x=x/g*inv%mm;
    34             for(int k=0;k<P/mm;k++)
    35                 if (!vis[i][P][k*mm+x]){
    36                     tot[i][P]++;
    37                     vis[i][P][k*mm+x]=1;
    38                     if (p)v_del.push_back(del{i,P,k*mm+x});
    39                 }
    40         }
    41     ans=0;
    42     for(int i=0;i<X;i++){
    43         double s=1;
    44         for(int j=1;j<=100;j++)s*=1.0*(j-tot[i][j])/j;
    45         ans+=s;
    46     }
    47     while (v_del.size()){
    48         del o=v_del.back();
    49         tot[o.i][o.P]--;
    50         vis[o.i][o.P][o.x]=0;
    51         v_del.pop_back();
    52     }
    53 }
    54 int main(){
    55     phi[1]=1;
    56     for(int i=2;i<N;i++){
    57         if (!visp[i]){
    58             p[++p[0]]=i;
    59             phi[i]=i-1;
    60         }
    61         for(int j=1;(j<=p[0])&&(i*p[j]<N);j++){
    62             visp[i*p[j]]=1;
    63             if (i%p[j])phi[i*p[j]]=phi[i]*phi[p[j]];
    64             else{
    65                 phi[i*p[j]]=phi[i]*p[j];
    66                 break;
    67             }
    68         }
    69     }
    70     scanf("%d",&n);
    71     for(int i=1;i<=n;i++){
    72         scanf("%d%d%d",&x,&r,&g);
    73         v.clear();
    74         for(int j=0;j<r+g;j++)
    75             if ((j+x)%(r+g)>=r)v.push_back(j);
    76         add(1,r+g,v);
    77         printf("%.9f
    ",ans/X);
    78         v.clear();
    79         for(int j=0;j<r+g;j++)
    80             if ((j+x)%(r+g)<r)v.push_back(j);
    81         add(0,r+g,v);
    82     }
    83     printf("%.9f",ans/X);
    84 } 
    View Code
  • 相关阅读:
    【Tools】xshell添加命令按钮Button
    【Optimization】ARM的寻址方式(详细)
    【Python】python文件或文本加密(4种方法)
    【Optimization】常用SSE Intrinsic指令总结
    【Optimization】X86汇编快速入门
    【Base】如何理解Latency和Throughput: 吞吐量和延迟
    【Cmd】Windows下批处理常用命令总结
    【Optimization】SSE指令集学习:Compiler Intrinsic
    【ASM】汇编指令movdqa与movdqu的区别
    anaconda
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14669487.html
Copyright © 2011-2022 走看看