#loj3093 [BJOI2019]光线

一开始推合并两个镜子的做法

然后自闭了

于是开始写消元,发现矩阵很有特点稍微优化下就行了

可以将每个镜子拆成正面和反面两个点,然后连边建高斯消元的图

将点以特定的方式重新编号之后发现可以从矩阵的左上角开始进行代入消元法

那剩下的事情就好说了,使用map存储整个矩阵就可以了

\(O(nlogn)\)

// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;typedef long long ll;const ll mod=1e9+7;
const int N=1e6+10;
inline ll po(ll a,ll p){ll r=1;for(;p;p>>=1,a=a*a%mod)if(p&1)r=r*a%mod;return r;}
//ll mp[N][N];
map <int,ll> mp[N];
bool book[N];ll cval[N];
inline void solve(int row)
{
    ll sum=0;int ns=-1;ll xs=0;
    for(map <int,ll> :: iterator it=mp[row].begin();it!=mp[row].end();++it)
        if(book[it->first])(sum+=(mod-it->second)*cval[it->first])%=mod;
        else ns=it->first,xs=po(it->second,mod-2);
//  printf("solve %d,ns=%d\n",row,ns);
    cval[ns]=sum*xs%mod;book[ns]=true;
}
int n;int S;
/*inline void prit()
{
    for(int i=1;i<=S;i++)
    {
        for(int j=1;j<=S+1;j++)
            printf("%lld ",mp[i].count(j));printf("\n");
    }
    printf("\n");
}*/
/*inline void gauss()
{
    prit();
    for(int i=1;i<=S;i++)
    {
    //  prit();
        if(mp[i][i]==0)
        {
            for(int j=i+1;j<=S;j++)
                if(mp[j][i]!=0)
                {
                    for(int k=i;k<=S+1;k++)swap(mp[i][k],mp[j][k]);
                    break;
                }
        }
        ll iv=po(mp[i][i],mod-2);
        for(int k=i;k<=S+1;k++)
            (mp[i][k]*=iv)%=mod;
        for(int j=1;j<=S;j++)
            if(j!=i)
            {   
                for(int k=S+1;k>=i;k--)
                    (mp[j][k]+=(mod-mp[j][i])*mp[i][k])%=mod;
            }
    }
}*/
ll fa[N];ll fb[N];
inline void push(int u,int v,ll val)
{
//  printf("add %d %d\n",u,v);
    (mp[u][v]+=mod-val)%=mod;
}
int main()
{
    ll iv100=po(100,mod-2);
    scanf("%d",&n);
    S=2*n;
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&fa[i],&fb[i])
        ,(fa[i]*=iv100)%=mod,
        (fb[i]*=iv100)%=mod;
    for(int i=1;i<n;i++)
        push(i<<1,(i+1)<<1,fa[i]);
    for(int i=n;i>=2;i--)
        push(i<<1|1,(i-1)<<1|1,fa[i]);
    for(int i=2;i<=n;i++)
        push(i<<1,(i-1)<<1|1,fb[i]);
    for(int i=1;i<n;i++)
        push(i<<1|1,(i+1)<<1,fb[i]);
    for(int i=1;i<=2*n;i++)
        mp[i][i]=1;
    //prit();
    //(mp[n<<1][S+1]+=fa[n])%=mod;
    //gauss();
    cval[2]=1;book[2]=true;
    for(int i=2;i<(n<<1);i++)
        solve(i);
    ll sum=0;
    for(map <int,ll >:: iterator it=mp[n<<1].begin();it!=mp[n<<1].end();++it)
        (sum+=it->second*cval[it->first])%=mod;
    printf("%lld",fa[n]*po(sum,mod-2)%mod);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sweetphoenix/p/10815176.html