zoukankan      html  css  js  c++  java
  • bzoj 4872 [Shoi2017]分手是祝愿

    题面

    https://www.lydsy.com/JudgeOnline/problem.php?id=4872

    题解

    首先解法是唯一的

    所以我们算出最少要按几次 然后如果<=k那么就这么按 获得80分(真多啊...)

    然后我们令f[i]表示当前离结果还有i步,我们要得到结果的期望步数

    又因为f[k]=k 所以我们可以解出所有的f

    f[最少要按几次]*n!就是答案

    我们可以递推 设f[i]=Af[i+1]+B 这样我们从k+1跑到n 每一个i的A,B都可以求出来 这样我们就解出了f[n]

    然后记录下每一个i对应的A,B 逆着推回去 就能解出f[最少要按几次]

    但是由于不知名问题 我的这个写法只获得95分 可能在取模和求逆元的过程中出现了问题

    于是我因为这种方法不是正解(失去调试的耐心)而放弃了这种做法

    然后百度一下

    差分!!!

    考虑差分f,或者说g[i]表示i到i-1步的期望步数

     

    这样得到

    g[i]=((n-i)(g[i]+1)+n)/i

    然后答案就是(g[m]+...+g[k+1]+k)*n!

    Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 
     5 ll read(){
     6     ll x=0,f=1;char c=getchar();
     7     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
     8     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
     9     return x*f;
    10 }
    11 
    12 const int mod=100003;
    13 int n,k;
    14 int a[100100];
    15 
    16 int ksm(int x,int p){
    17     int ret=1;
    18     while(p){
    19         if(p&1) ret=ret*1ll*x%mod;
    20         x=x*1ll*x%mod;
    21         p=p>>1;
    22     }
    23     return ret;
    24 }
    25 
    26 int p[100100];
    27 int recA[100100],recB[100100];
    28 int main(){
    29 #ifdef LZT
    30     freopen("in","r",stdin);
    31 #endif
    32     n=read(),k=read();
    33     for(int i=1;i<=n;i++)
    34         a[i]=read();
    35     int m=0;
    36     for(int i=n;i>=1;i--){
    37         if(a[i]){
    38             m++;
    39             for(int j=1;j*j<=i;j++){
    40                 if(i%j!=0) continue;
    41                 a[j]^=1;
    42                 if(j*j!=i) a[i/j]^=1;
    43             }
    44         }
    45     }
    46     if(k>=m){
    47         for(int i=1;i<=n;i++)
    48             m=m*1ll*i%mod;
    49         printf("%d
    ",m);
    50         return 0;
    51     }
    52     int t=ksm(n,mod-2);
    53     //cout<<t<<endl;
    54     p[k]=k;
    55     int A=0,B=0;
    56     for(int x=k+1;x<=n;x++){
    57         if(x==k+1){
    58             A=t*1ll*(n-x)%mod;
    59             B=(t*1ll*x%mod*p[x-1]%mod+1)%mod;
    60             recA[x]=A;
    61             recB[x]=B;
    62             //cout<<A<<' '<<B<<endl;
    63             continue;
    64         }
    65         int nw=t*1ll*x%mod*A%mod;
    66         nw=(1-nw+mod)%mod;
    67         nw=ksm(nw,mod-2);
    68         A=nw*1ll*t%mod*(n-x)%mod;
    69         B=nw*1ll*(t*1ll*x%mod*B%mod+1)%mod;
    70         recA[x]=A;
    71         recB[x]=B;
    72         //cout<<A<<' '<<B<<endl;
    73     }
    74     int val=B;
    75     for(int i=n-1;i>=m;i--)
    76         val=(recA[i]*1ll*val%mod+recB[i]%mod)%mod;
    77     for(int i=1;i<=n;i++)
    78         val=val*1ll*i%mod;
    79     printf("%d
    ",val);
    80     return 0;
    81 }
    95分的代码
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 
     5 ll read(){
     6     ll x=0,f=1;char c=getchar();
     7     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
     8     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
     9     return x*f;
    10 }
    11 
    12 const int mod=100003;
    13 int n,k;
    14 int a[100100];
    15 
    16 int ksm(int x,int p){
    17     int ret=1;
    18     while(p){
    19         if(p&1) ret=ret*1ll*x%mod;
    20         x=x*1ll*x%mod;
    21         p=p>>1;
    22     }
    23     return ret;
    24 }
    25 
    26 int p[100100];
    27 //int recA[100100],recB[100100];
    28 int main(){
    29 #ifdef LZT
    30     freopen("in","r",stdin);
    31 #endif
    32     n=read(),k=read();
    33     for(int i=1;i<=n;i++)
    34         a[i]=read();
    35     int m=0;
    36     for(int i=n;i>=1;i--){
    37         if(a[i]){
    38             m++;
    39             for(int j=1;j*j<=i;j++){
    40                 if(i%j!=0) continue;
    41                 a[j]^=1;
    42                 if(j*j!=i) a[i/j]^=1;
    43             }
    44         }
    45     }
    46     if(k>=m){
    47         for(int i=1;i<=n;i++)
    48             m=m*1ll*i%mod;
    49         printf("%d
    ",m);
    50         return 0;
    51     }
    52     int t=ksm(n,mod-2);
    53     /*
    54     //cout<<t<<endl;
    55     p[k]=k;
    56     int A=0,B=0;
    57     for(int x=k+1;x<=n;x++){
    58         if(x==k+1){
    59             A=t*1ll*(n-x)%mod;
    60             B=(t*1ll*x%mod*p[x-1]%mod+1)%mod;
    61             recA[x]=A;
    62             recB[x]=B;
    63             //cout<<A<<' '<<B<<endl;
    64             continue;
    65         }
    66         int nw=t*1ll*x%mod*A%mod;
    67         nw=(1-nw+mod)%mod;
    68         nw=ksm(nw,mod-2);
    69         A=nw*1ll*t%mod*(n-x)%mod;
    70         B=nw*1ll*(t*1ll*x%mod*B%mod+1)%mod;
    71         recA[x]=A;
    72         recB[x]=B;
    73         //cout<<A<<' '<<B<<endl;
    74     }
    75     int val=B;
    76     for(int i=n-1;i>=m;i--)
    77         val=(recA[i]*1ll*val%mod+recB[i]%mod)%mod;
    78     for(int i=1;i<=n;i++)
    79         val=val*1ll*i%mod;
    80     printf("%d
    ",val);*/
    81     p[n]=1;
    82     for(int i=n-1;i>k;i--)
    83         p[i]=((n-i)*1ll*p[i+1]%mod+n)%mod*1ll*ksm(i,mod-2)%mod;
    84     int val=0;
    85     for(int i=m;i>k;i--)
    86         val=(val+p[i])%mod;
    87     val=val+k;
    88     for(int i=1;i<=n;i++)
    89         val=val*1ll*i%mod;
    90     printf("%d
    ",val);
    91     return 0;
    92 }
    100分的代码

    Review

    动机?

    到95分为止都是自己想到的 也不是很难想

    然后差分... 这个怎么想到的我也不是很清楚

    (如果递推式没法推就差分一下?)

  • 相关阅读:
    【mysql】关于IO/内存方面的一些优化
    【mysql】使用tpcc-mysql进行压力测试
    Linux下使用iostat 监视I/O状态
    【JUC】JUC线程池框架综述
    【目录】JUC集合框架目录
    【JUC】JDK1.8源码分析之ConcurrentSkipListSet(八)
    【JUC】JDK1.8源码分析之CopyOnWriteArraySet(七)
    【JUC】JDK1.8源码分析之CopyOnWriteArrayList(六)
    【设计模式】策略模式
    【JUC】JDK1.8源码分析之ConcurrentLinkedQueue(五)
  • 原文地址:https://www.cnblogs.com/wawawa8/p/9378923.html
Copyright © 2011-2022 走看看