您的位置:首页 > 产品设计 > UI/UE

【UOJ 209】【UER #6】票数统计

2016-07-08 12:09 375 查看

Description

原题链接

妹滋滋是一个善于编程的女孩子。

但是某一天,她一不小心把 UOJ 后台的票数统计程序写错了。

本来嘛在这种根本没有什么用的功能上出了 bug 也没有什么大关系,但是又有某一天,UOJ 突然就开始搞全民公投了。

这可怎么办呢?如果这个消息让别人知道的话自己肯定会被查表,更不要说让所有用户重新来投一次票了。

作为一个要强的女孩子,妹滋滋决定自力更生。

通过一些奥妙重重的方式,妹滋滋知道了一些关于这次全民公投的信息。

这次全民公投一共有 n 位用户排队参加,编号为 1 到 n。每一位用户要么投了通过,要么投了不通过。

有 mm 个二元组 (xi,yi),每个二元组给出这样一个信息: “前 xi位用户中,恰好 yi 位投了通过” 和 “后 yi 位用户中,恰好有 xi 位投了通过” 这两句话中,至少有一句是成立的。

作为分析的第一步,她想要知道有多少种投票情况是满足她所得到的信息的。当然,可能所有投票情况都不满足条件。

Solution

很显然,当x>y时就是第二种情况,

而对于所有的x=y的情况,只有最大x是有用的,

所有我们枚举所有投票的人,这样所有的对后缀的限制就变成了前缀,

于是可以愉快的用C公式搞,

对于x=y,只要符合前缀的情况+符合后缀的情况-两个多符合的情况即可,

复杂度:O(n2)

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long LL;
const int N=5555,mxlongint=2147483640,mo=998244353;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n,m,m1,c;
LL ans;
struct qqww
{int x,y,s;}a
;
LL C

;
bool PX(qqww a,qqww b)
{
int q=a.x,w=b.x;
if(a.s==1||a.s==2)q=n-q+1;
if(b.s==1||b.s==2)w=n-w+1;
return (q<w)||((q==w)&&(a.s>b.s));
}
LL ss(int m1)
{
int q,w,e=m;
LL ans,ANS=0;
int l=0,l1=0,c1,c2;
fo(i,1,m)if(a[i].s!=2)
{
if(a[i].s==1)
{
q=n-a[i].x,w=m1-a[i].y;
if(a[i].y+a[i].x-1<m1){l1=n;break;}
}
else
{
q=a[i].x,w=a[i].y;
if(a[i].s==0){l1=n;break;}
}
if(a[i].s==-1){e=i;break;}
if(w<0||q<0)return 0;
if(!C[q-l][w-l1])return 0;
l=q,l1=w;
}
if(l1<=c&&l1+q-l>=c)
{
c1=e;
l=l1=a[e].x;ans=1;
fo(i,e+1,m)if(a[i].s!=2)
{
if(a[i].s==1)q=n-a[i].x,w=m1-a[i].y;else q=a[i].x,w=a[i].y;
if(w-l1<0||q<0)ans=0;
ans=(ans*C[q-l][w-l1])%mo;
if(!ans)break;
l=q,l1=w;
}
if(n-l<0||m1-l1<0)ans=0;else ans=(ans*C[n-l][m1-l1])%mo;
ANS=ans;
if(!ans)c1=0;
}else c1=0;
if(!c)return ANS;
l=n+1,l1=e=0;
fod(i,m,1)if(a[i].s!=-1)
{
if(a[i].s==0)
{
q=a[i].x,w=m1-a[i].y;
if(a[i].y+n-a[i].x<m1){l1=n;break;}
}
else
{
q=n-a[i].x,w=a[i].y;
if(a[i].s==1){l1=n;break;}
}
if(a[i].s==2){e=i;break;}
if(w-l1<0||q<0)return 0;
if(!C[l-q][w-l1])return 0;
l=q,l1=w;
}
if(l1<=c&&l1+l-q>=c)
{
l1=a[e].x,l=n-a[e].x;ans=1;
c2=e;
fod(i,e-1,1)if(a[i].s!=-1)
{
if(!a[i].s)q=a[i].x,w=m1-a[i].y;else q=n-a[i].x,w=a[i].y;
if(w-l1<0||q<0)ans=0;
ans=(ans*C[l-q][w-l1])%mo;
if(!ans)break;
l=q,l1=w;
}
if(n-l<0||m1-l1<0)ans=0;else ans=(ans*C[l][m1-l1])%mo;
ANS+=ans;
}else c2=0;
if(ans&&c1&&c2)
if(c*2>=n)ANS-=(m1==n);
else if(m1>=c*2)
{
l=l1=a[e].x;ans=1;
fo(i,c1+1,c2-1)
{
if(a[i].s==1)q=n-a[i].x,w=m1-a[i].y;else q=a[i].x,w=a[i].y;
if(w-l1<0||q<0)ans=0;
ans=(ans*C[q-l][w-l1])%mo;
if(!ans)break;
l=q,l1=w;
}
ans=(ans*C[n-c-l][m1-l1-c])%mo;
ANS-=ans;
}
return ANS%mo;
}
int main()
{
int q,w,_,mx;
fo(i,0,N-550)
{
C[i][0]=1;
fo(j,1,i)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mo;
}
read(_);
while(_--)
{
read(n),read(m);
m1=c=0;mx=1;
ans=0;
fo(i,1,m)
{
q=read(a[++m1].x),w=read(a[m1].y);
if(q>n||w>n)ans=-1;
if(q>w)a[m1].s=0,mx=max(mx,a[m1].y);
else if(q<w)a[m1].s=1,swap(a[m1].x,a[m1].y),mx=max(mx,a[m1].y);
else
{
if(c<a[m1].x)c=a[m1].x;
m1--;
}
}
m=m1;
a[++m].x=a[m].y=c,a[m].s=-1;
if(c)a[++m].x=a[m].y=c,a[m].s=2;
sort(a+1,a+1+m,PX);
fo(i,2,m)
if(a[i].x==a[i-1].x&&a[i].s==a[i-1].s&&a[i].y!=a[i-1].y)ans=-1;
if(c==n&&m>2)ans=-1;
if(ans==-1){printf("0\n");continue;}
fo(i,mx,n)ans=(ans+ss(i))%mo;
printf("%d\n",(ans+mo)%mo);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: