【UER #6】票数统计
安利了官解http://jiry_2.blog.uoj.ac/blog/1789
很多地方没来得及删,将就着先
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (998244353)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int n,m;
#define MAXN (5000+10)
#define MAXM (5000+30)
pi p[MAXM],p2[MAXM],p3[MAXM];
void work1(){
int ans=0;
Rep(S,1<<n) {
bool flag=0;
Rep(i,m) {
int a=S%(1<<p[i].se);
int b=S>>(n-p[i].fi);
if(__builtin_popcount(a)==p[i].fi||__builtin_popcount(b)==p[i].se); else {flag=1;break;}
}
if (!flag) {++ans; /*cout<<S<<'x'<<endl;*/}
}
cout<<ans<<endl;
}
ll C[MAXN][MAXN],t2[MAXN];
void pre() {
int n=5005;
C[0][0]=1;
For(i,n) {
C[i][0]=1;
For(j,i) C[i][j]=add(C[i-1][j-1],C[i-1][j]);
}
t2[0]=1;
For(i,n) t2[i]=mul(t2[i-1],2);
}
ll pow2(ll a,int b,ll p) //a^b mod p
{
if (a==2&&b<=5000) return t2[b];
if (b==0) return 1%p;
if (b==1) return a%p;
ll c=pow2(a,b/2,p)%p;
c=c*c%p;
if (b&1) c=c*a%p;
return c%p;
}
int c[MAXM];
ll work2(pi *p,int m) {
Rep(i,m) {
// if (p[i].fi<p[i].se) swap(p[i].fi,p[i].se);
if (p[i].se<0) return 0;
}
memset(c,-1,sizeof(c));
Rep(i,m) {
if (c[p[i].fi]==-1 || c[p[i].fi]==p[i].se ) {
c[p[i].fi]=p[i].se;
} else return 0;
}
m=0;
Rep(i,n+1) if (c[i]^(-1)) p[m++] = mp(i,c[i]);
// sort(p,p+m);
// m=unique(p,p+m)-p;
Rep(i,m-1) {
if (p[i].fi==p[i+1].fi&&p[i].se!=p[i+1].se) return 0;
if (p[i].fi<p[i+1].fi&&p[i].se>p[i+1].se) return 0;
}
ll ans=1;
if (m) ans=C[p[0].fi][p[0].se];
Rep(i,m-1) {
ll a=p[i+1].fi-p[i].fi;
ll b=p[i+1].se-p[i].se;
ans=mul(ans,C[a][b]);
}
ll t=n-p[m-1].fi;
ans=mul(ans,pow2(2,t,F));
return ans;
}
void work3() {
int mx=0;
Rep(i,m) if (p[i].fi==p[i].se) {
mx=max(mx,p[i].fi);
}
ll ans=0;
Rep(S,n+1) {
int cm=0;
Rep(i,m)
if (p[i].fi<p[i].se) p2[cm++]=mp(n-p[i].se,S-p[i].fi);
else if (p[i].fi>p[i].se) p2[cm++]=p[i];
p2[cm++]=mp(n,S);
memcpy(p3,p2,sizeof(pi)*cm);
p3[cm++]=mp(mx,mx);
upd(ans,work2(p3,cm));
memcpy(p3,p2,sizeof(pi)*(cm-1));
p3[cm-1]=mp(n-mx,S-mx);
upd(ans,work2(p3,cm));
memcpy(p3,p2,sizeof(pi)*(cm-1));
p3[cm-1]=mp(mx,mx);
p3[cm++]=mp(n-mx,S-mx);
ans=sub(ans,work2(p3,cm));
ans=(ans%F+F)%F;
}
cout<<ans<<endl;
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("problem_209/ex_a2.in","r",stdin);
// freopen(".out","w",stdout);
pre();
int T=read();
while(T--) {
n=read();
m=read();
bool fl=0;
Rep(i,m) {
p[i].fi=read(),p[i].se=read();
if (p[i].fi>=p[i].se) fl=1;
}
if (n<=20&&m<=20) work1();
else if (!fl) {
Rep(i,m) swap(p[i].fi,p[i].se);
cout<<work2(p,m)<<endl;
}
else work3();
}
return 0;
}
本文介绍了一个名为UER6票数统计的程序,该程序使用C++编写,涉及复杂的算法逻辑,包括位运算、组合数学等高级数据结构与算法。通过多种循环和条件判断实现了对特定条件下的票数进行计算。
872

被折叠的 条评论
为什么被折叠?



