D. Rescue Nibel!_编程题目
题意:总共有n个线段,问选择k条线段,使得他们相交于一点的方案数。
思路:用类似差分的思想,将每条线段的l和r+1放进数组里并且分别带有1和-1的权值,将数组按照坐标大小排序,如果坐标大小不同按照权制大小排序,权值小的放在前面,然后依次遍历下来,把方案定义为以第i个灯泡为末尾(即该灯泡的坐标在选的坐标里最大)的方案数,这些方案是不重不漏的,加起来就是答案了,然后模数不是质数,要用扩展欧几里得求,然后我忘了咋写了。

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node{
    ll x;
    int d;
    bool operator <(const node&W)const
    {
        if(x==W.x)
            return d<W.d;
        return x<W.x;
    }
};
const int N=600010;
const int mod= 998244353;
node q[N];
int cnt;
ll fact[N];
ll infact[N];
ll qmi(ll a,int b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res%mod;
}
ll exgcd(ll a,ll b,ll &x,ll & y);
void init()
{
    fact[0]=infact[0]=1;
    for(int i=1;i<N;i++)
    {
        fact[i]=fact[i-1]*i%mod;
        ll x, y;
        ll d=exgcd(fact[i],mod,x,y);
        infact[i]=(x%mod+mod)%mod;
    }
}
ll C(ll a,ll b)
{
    if(b>a) return 0;
    return fact[a]*infact[a-b]%mod*infact[b]%mod;
}
ll exgcd(ll a,ll b,ll &x,ll & y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
int main()
{
    int n,m;
    init();
   // cout<<fact[3]<<' '<<C(6,3)<<endl;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        int l,r;
        cin>>l>>r;
        q[cnt++]={l,1};
        q[cnt++]={r+1,-1};
    }
    sort(q,q+cnt);
    int ct=0;
    ll res=0;
    for(int i=0;i<cnt;i++)
    {
        //cout<<ct<<endl;
        if(q[i].d==1)
        res = (res+C(ct,m-1))%mod;
        ct+=q[i].d;
    }
    cout << res << endl;
    return 0;
}