zoukankan      html  css  js  c++  java
  • Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线

    题目描述

    当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收。

    设对于任意 (x),有 (x imes a_i\%) 单位的光会穿过它,有 (x imes b_i\%) 的会被反射回去。

    现在 (n) 层玻璃叠在一起,有 (1) 单位的光打到第 (1) 层玻璃上,那么有多少单位的光能穿过所有 (n) 层玻璃呢?

    输入格式

    第一行一个正整数 (n),表示玻璃层数。

    接下来 (n) 行,每行两个非负整数 (a_i,b_i),表示第 (i) 层玻璃的透光率和反射率。

    输出格式

    输出一行一个整数,表示穿透所有玻璃的光对 (10^9 + 7) 取模的结果。

    可以证明,答案一定为有理数。设答案为 (a/b)(a)(b) 是互质的正整数),你输出的答案为 (x),你需要保证 (aequiv bx pmod {10^9 + 7})

    数据范围与提示

    对于 (5\%) 的数据,保证 (n=1)

    对于 (20\%) 的数据,保证 (nle 2)

    对于 (30\%)的数据,保证 (nle 3)

    对于 (50\%) 的数据,保证 (nle 100)

    对于 (70\%) 的数据,保证 (nle 3000)

    对于 (100\%) 的数据:

    - (1le nle 5 imes 10^5)

    - (1le a_i le 100)

    - (0le b_i le 99)

    - (1le a_i+b_i le 100)

    - 每组 (a_i)(b_i) 在满足上述限制的整数中随机生成。

    (\)

    (f_i)表示一单位光从上至下打到第(i)块玻璃之后能穿过第(n)块玻璃的单位数量。

    (g_i)表示一单位光从下至上打到第(i)块玻璃之后能穿过第(n)块玻璃的单位数量。

    特别地(g_0=0,f_{n+1}=1)

    于是我们容易得到:

    [f_i=a_i\%f_{i+1}+b_i\%g_{i-1} (1leq ileq n)\ Rightarrow f_{i+1}=frac{f_i-b_i\%g_{i-1}}{a_i\%}\ ]

    这里不需要考虑(a_i=0)的问题,因为(a_i=0)时答案为(0),特判掉就好了。

    以及:

    [g_i=a_i\% *g_{i-1}+b_i\% *f_{i+1} (1leq ileq n)\ ]

    我们可以设(f_1=x),然后按照上面两个(DP)(f_{n+1})(x)表示时的系数。答案就是(frac{1}{f_{n+1}})

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define N 500005
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    const ll mod=1e9+7;
    ll ksm(ll t,ll x) {
    	ll ans=1;
    	for(;x;x>>=1,t=t*t%mod)
    		if(x&1) ans=ans*t%mod;
    	return ans;
    }
    
    int n;
    ll a[N],b[N];
    const ll inv100=ksm(100,mod-2);
    ll f[N],g[N];
    
    int main() {
    	n=Get();
    	for(int i=1;i<=n;i++) {
    		a[i]=inv100*Get()%mod,b[i]=inv100*Get()%mod;
    	}
    	for(int i=1;i<=n;i++) {
    		if(a[i]==0) {cout<<0;return 0;}
    	}
    	f[1]=1;
    	f[2]=ksm(a[1],mod-2);
    	g[1]=b[1]*f[2]%mod;
    	for(int i=2;i<=n;i++) {
    		f[i+1]=(f[i]-b[i]*g[i-1]%mod+mod)*ksm(a[i],mod-2)%mod;
    		g[i]=(a[i]*g[i-1]+b[i]*f[i+1])%mod;
    	}
    	cout<<ksm(f[n+1],mod-2);
    	return 0;
    }
    
    
  • 相关阅读:
    bootstrap 导航栏、输入框按钮组、栅格系统
    Python排序算法冒泡排序选择排序插入排序
    Python 解螺旋数组
    初到博客园,请多指教
    gcd, map for ocaml
    qsort for ocaml
    子序列和最大的问题
    将一个整数划分为非负整数的部分
    filter in Ocaml
    scheme中表只能操作头部带来的一个问题
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10784663.html
Copyright © 2011-2022 走看看