Processing math: 100%

[BJOI2019]光线——递推

原题看我

题解

如果能把多块玻璃合并到一起多棒啊,但是直接把多块合并似乎不太可能,考虑两两合并
也就是已知上下层玻璃的透光率分别为a1%a2%,反射率分别为b1%b2%,求一块等效的玻璃,使得它和两块玻璃叠在一起的效果相同
(有一点要注意一下,就是合并后的玻璃上下的反射率和透光率不一定相同,我们需要根据合并的方向来判断要计算的是哪一个
也就是下面这两幅图,为了方便,将x%省略成x
1.
即合并后的透光率为a1a2i=0(b1b2)i=a1a21b1b2
2.
即合并后的(向下的)反射率为b2+a22b1i=0(b1b2)i=a22b11b1b2+b2
(P.S. 图中左下角的那个应该是b2)
这样我们就可以O(n)的递推了
代码如下:

#include <algorithm>
#include  <iostream>
#include   <cstdlib>
#include   <cstring>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <cmath>
#include     <ctime>
#include     <queue>
#include       <map>
#include       <set>

using namespace std;

#define ull unsigned long long
#define pii pair<int, int>
#define uint unsigned int
#define mii map<int, int>
#define lbd lower_bound
#define ubd upper_bound
#define INF 0x3f3f3f3f
#define IINF 0x3f3f3f3f3f3f3f3fLL
#define vi vector<int>
#define ll long long
#define mp make_pair
#define pb push_back
#define re register
#define il inline

#define MOD 1000000007

int n;
int p100;
int A, B;

int fpow(int x, int p) {
  int ret = 1;
  while(p) {
    if(p&1) ret = 1LL*ret*x%MOD;
    x = 1LL*x*x%MOD;
    p >>= 1;
  }
  return ret;
}

int read() {
  int t;
  scanf("%d", &t);
  return 1LL*t*p100%MOD;
}

int main() {
  scanf("%d", &n);
  p100 = fpow(100, MOD-2);
  A = read(), B = read();
  for(int i = 2, a, b, t; i <= n; ++i) {
    a = read(), b = read();
    t = fpow((1-1LL*B*b%MOD+MOD)%MOD, MOD-2);
    A = 1LL*A*a%MOD*t%MOD;
    B = (1LL*a*a%MOD*B%MOD*t%MOD+b)%MOD;
  }
  printf("%d\n", A);
  return 0;
}
posted @   dummyummy  阅读(179)  评论(0编辑  收藏  举报
编辑推荐:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
阅读排行:
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
· 用 C# 插值字符串处理器写一个 sscanf
点击右上角即可分享
微信分享提示