QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#104423 | #6399. Classic: Classical Problem | changtu | WA | 2ms | 5708kb | C++23 | 5.7kb | 2023-05-10 17:42:32 | 2023-05-10 17:42:35 |
Judging History
answer
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
// #define debug(x) cout<<"[debug]"#x<<"="<<x<<endl
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
const ld eps=1e-8;
const int INF=0x3f3f3f3f;
#define ONLINE_JUDGE
#ifndef ONLINE_JUDGE
#define debug(...)
#include<debug>
#else
#define debug(...)
#endif
namespace NTT
{
typedef vector<ll> Poly;
const int mod=998244353,G=3,Gi=332748118;
const int M=6e5;//TODO
int bit,tot;
int rev[M];
ll qmi(ll a,ll b,ll p)
{
ll res=1;
while(b)
{
if(b&1)
res=res*a%p;
a=a*a%p;
b>>=1;
}
return res;
}
void NTT(Poly &a,int inv)
{
for(int i=0;i<tot;i++)
if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int mid=1;mid<tot;mid*=2)
{
ll w1=qmi(inv==1?G:Gi,(mod-1)/(2*mid),mod);
for(int i=0;i<tot;i+=mid*2)
{
ll wk=1;
for(int j=0;j<mid;j++,wk=wk*w1%mod)
{
ll x=a[i+j];
ll y=wk*a[i+j+mid]%mod;
a[i+j]=(x+y)%mod;
a[i+j+mid]=(x-y+mod)%mod;
}
}
}
if(inv==-1)//就不用后面除了
{
ll intot=qmi(tot,mod-2,mod);
for(int i=0;i<tot;i++)
{
a[i]=a[i]*intot%mod;
}
}
}
Poly mul(Poly a,Poly b)//deg是系数的数量,所以有0~deg-1次项
{
int deg=(int)a.size()+b.size()-1;
bit=0;
while((1<<bit)<deg) bit++;//至少要系数的数量
tot=1<<bit; //系数项为0~tot-1
for(int i=0;i<tot;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
Poly c(tot);
a.resize(tot),b.resize(tot);
NTT(a,1),NTT(b,1);
for(int i=0;i<tot;i++) c[i]=a[i]*b[i]%mod;
NTT(c,-1);
c.resize(deg);
return c;
}
Poly operator *(const Poly &a,const Poly &b)
{
return mul(a,b);
}
Poly operator *(const Poly &a,const int &t)
{
Poly res;
for(int i=0;i<a.size();i++) res.push_back(1ll*a[i]*t%mod);
return res;
}
Poly operator *(const Poly &a,const ll &t)
{
Poly res;
for(int i=0;i<a.size();i++) res.push_back(a[i]*t%mod);
return res;
}
Poly operator +(const Poly &a,const Poly &b)
{
Poly res(a);
res.resize(max(a.size(),b.size()));
for(int i=0;i<b.size();i++) res[i]=(res[i]+b[i])%mod;
return res;
}
Poly operator -(const Poly &a,const Poly &b)
{
Poly res(a);
res.resize(max(a.size(),b.size()));
for(int i=0;i<b.size();i++) res[i]=(res[i]-b[i]+mod)%mod;
return res;
}
}
using namespace NTT;
const int N=200005;
int n,p,g;
int a[N];
int ind[N];//指标
int get_gen(int m)
{
//if(!check(m)) return ;
int phip=m-1;//m为质数的情况是m-1,否则需要求phi(m)
for(int gen=2;;gen++)
{
if(__gcd(gen,m)!=1) continue;
int t=phip;
bool ok=true;
for(int i=2;i<=t/i;i++)
{
if(t%i==0)
{
if(qmi(gen,phip/i,m)==1)
{
ok=false;
break;
}
while(t%i==0) t/=i;
}
}
if(t!=1&&qmi(gen,phip/t,m)==1) ok=false;
if(ok) return gen%m;
}
}
void solve()
{
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
if(p==1)
{
puts("1 1");
puts("0");
return ;
}
else if(p==2)
{
int maxi=-1;
vector<int> pathc;
for(int c=0;c<p;c++)
{
vector<bool> st(3);
for(int i=1;i<=n;i++)
{
st[a[i]]=true;
}
int mex=0;
while(st[mex]) mex++;
if(mex>maxi) maxi=mex,pathc.clear();
if(mex==maxi) pathc.push_back(mex);
}
printf("%d %d\n",pathc.size(),maxi);
for(auto c:pathc) printf("%d ",c);
puts("");
return ;
}
bool no_zero=true;
for(int i=1;i<=n;i++) if(!a[i]) no_zero=false;
if(no_zero)
{
puts("1 1");
puts("0");
return ;
}
g=get_gen(p);
for(int i=0;i<p-1;i++) ind[qmi(g,i,p)]=i;//下标1~p-1分别对应的指标0~p-2
Poly B(p-1);
for(int i=1;i<=n;i++)
{
if(a[i]==0) continue;
int t=ind[a[i]];
B[t]=1;
}
reverse(B.begin(),B.end());
vector<int> pathc;
auto check=[&](int mid){
if(mid==0)
{
return true;
}
Poly A(p-1);
for(int i=1;i<=mid;i++) A[ind[i]]=1;//1~mex-1对应的指标
Poly res=A*B;
pathc.clear();
//j-i+p-1 j-i=>x
for(int i=0;i<p-1;i++) res[i]+=res[i+p-1];
for(int i=0;i<p-1;i++)
{
if(res[i]==mid)
{
pathc.push_back(p-2-i);
}
}
return pathc.size()!=0;
};
int l=0,r=p-1;
while(l<r)//二分mex-1是否可行
{
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
check(l);
int mex=l+1;
for(auto &c:pathc) c=qmi(g,c,p);
if(mex==1) pathc.push_back(0);
sort(pathc.begin(),pathc.end());
printf("%d %d\n",pathc.size(),mex);
for(auto c:pathc) printf("%d ",c);
puts("");
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
solve();
}
}
详细
Test #1:
score: 100
Accepted
time: 2ms
memory: 5636kb
input:
3 2 3 0 2 3 5 2 3 4 3 5 0 2 3
output:
1 2 2 1 1 0 2 2 2 3
result:
ok 6 lines
Test #2:
score: -100
Wrong Answer
time: 2ms
memory: 5708kb
input:
3 1 2 0 1 2 1 2 2 1 0
output:
2 1 1 1 2 0 0 0 2 2 2 2
result:
wrong answer 2nd lines differ - expected: '0 1', found: '1 1 '