CQOI2018
和SCOI2018形成鲜明对比……
板子题+大力卡常。
作为大常数选手的我被卡得瑟瑟发抖。
发现自己板子还是不熟,常数还是太大,智障错误还是太多
D1T1



BSGS
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
ll n,A,B,mod,g,f,sz,a,b;
map<ll,int> G;
char cc; ll ff;
template<typename T>void read(T& aa) {
aa=0;cc=getchar();ff=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
aa*=ff;
}
ll qp(ll x,ll k) {
ll rs=1;
while(k) {
if(k&1) rs=rs*x%mod;
k>>=1; x=x*x%mod;
}
return rs;
}
ll get_ans(ll x) {
if(x==1) return 0;
For(i,0,mod) {
if(x==1) return i*sz;
if(G[x]) return i*sz+G[x];
x=x*f%mod;
}
}
int main() {
freopen("crack.in","r",stdin);
freopen("crack.out","w",stdout);
read(g); read(mod); sz=sqrt(mod);
ll x=1;
For(i,1,sz) {
x=x*g%mod;
if(!G[x]) G[x]=i;
}
f=qp(x,mod-2);
read(n);
For(i,1,n) {
read(A); read(B);
a=get_ans(A);
b=get_ans(B);
printf("%lld\n",qp(g,a*b));
}
return 0;
}
D1T2




Matrix Tree定理
今天早读的时候在打这个板子,然后WA了还没调出来,又遇到这道题,和早上WA的地方一模一样
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const ll mod=10007,maxn=500+7,maxm=maxn*maxn;
int n,m,id[maxn],tot;
ll D[maxn][maxn];
char cc; ll ff;
template<typename T>void read(T& aa) {
aa=0;cc=getchar();ff=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
aa*=ff;
}
int fir[maxn],nxt[maxm],to[maxm],e=0;
void add(int x,int y) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;
}
bool vis[maxn];
void s(int pos) {
if(vis[pos]) return;
vis[pos]=1;
for(int y=fir[pos];y;y=nxt[y]) s(to[y]);
}
void insert(int x,int y) {
D[x][y]--;
// D[y][x]--;
D[y][y]++;
}
ll Mtx(int n) {
ll a,b,r,rs=1,fl=0;
For(i,1,n) For(j,1,n) D[i][j]=(D[i][j]+mod)%mod;
For(i,1,n) {
For(j,i+1,n) if(D[j][i]) {
a=D[i][i]; b=D[j][i];
while(b) {
r=a/b; a=a%b; swap(a,b);
For(k,i,n) D[i][k]=(D[i][k]-D[j][k]*r%mod+mod)%mod;
swap(D[i],D[j]);
fl^=1;
}
}
if(D[i][i]==0) return 0;
rs=rs*D[i][i]%mod;
}
if(fl) rs=(mod-rs)%mod;
return rs;
}
int main() {
freopen("sns.in","r",stdin);
freopen("sns.out","w",stdout);
read(n); read(m);
int x,y;
For(i,1,m) {
read(x); read(y);
add(y,x);
}
s(1);
Rep(i,n,1) if(vis[i])
id[i]=++tot;
For(i,1,n) if(vis[i])
for(y=fir[i];y;y=nxt[y]) if(vis[to[y]])
insert(id[i],id[to[y]]);
printf("%lld\n",Mtx(tot-1));
return 0;
}
D1T3


不晓得正解是什么,我枚举1的个数然后用组合数直接算,被卡常卡得我妈都不认识了
然后用llj的优化方法,线筛预处理i^a和i^b,还是卡常。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
const int maxn=1e7+7;
ll n,W,a,b,mod,mi[maxn],inv[maxn],sum[maxn],p1[maxn],p2[maxn],ans,x,y;
ll num[maxn];
char cc; ll ff;
template<typename T>void read(T& aa) {
aa=0;cc=getchar();ff=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
aa*=ff;
}
inline ll qp(ll x,ll k) {
ll rs=1;
while(k) {
if(k&1) rs=rs*x%mod;
k>>=1; x=x*x%mod;
}
return rs;
}
int prime[maxn],totp;
bool ok[maxn];
inline void get_p() {
p1[0]=a==0;
p2[0]=b==0;
p1[1]=p2[1]=1;
For(i,2,W) {
if(!ok[i]) {
p1[i]=qp(i,a);
p2[i]=qp(i,b);
prime[++totp]=i;
}
For(j,1,totp) {
if(prime[j]*i>W) break;
ok[i*prime[j]]=1;
p1[i*prime[j]]=p1[i]*p1[prime[j]]%mod;
p2[i*prime[j]]=p2[i]*p2[prime[j]]%mod;
if(i%prime[j]==0) break;
}
}
}
inline ll C(ll n,ll m) {
if(sum[n]-sum[m]-sum[n-m]>0) return 0;
return mi[n]*inv[m]%mod*inv[n-m]%mod;
}
int main() {
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
read(n); read(a); read(b); read(mod);
W=n+3;
get_p();
// cerr<<clock()<<"\n";
mi[0]=1;
x=mod; while(x<=W) num[x]=1,x+=mod;
For(i,1,W) {
if(num[i]) sum[i]=sum[i/mod]+1,num[i]=num[i/mod];
else num[i]=i;
mi[i]=mi[i-1]*num[i]%mod;
}
For(i,1,W) sum[i]+=sum[i-1];
inv[W]=qp(mi[W],mod-2);
Rep(i,W,1)
inv[i-1]=inv[i]*num[i]%mod;
// cerr<<clock()<<"\n";
For(i,0,(n+1)>>1) {//tot of 1
x=n-i; //tot of 0
y=x-(i-1); //remain of 0
ans+=p1[x]*p2[i]%mod*C(y+i,y)%mod;
}
printf("%lld\n",ans%mod);
// cerr<<clock()<<"\n";
return 0;
}
D2T1



状压dp,我的记忆化搜索可以被卡60分的常?
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=23,maxt=(1<<19)+7;
const ll mod=1e8+7;
ll n,W,f[maxt][maxn],nd[maxn][maxn],cnt[maxt],ans;
char cc; ll ff;
template<typename T>void read(T& aa) {
aa=0;cc=getchar();ff=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
aa*=ff;
}
struct Xl{
ll x,y;
Xl(db x=0.,db y=0.):x(x),y(y){}
Xl operator + (const Xl& b) const{return Xl(x+b.x,y+b.y);}
Xl operator - (const Xl& b) const{return Xl(x-b.x,y-b.y);}
}p[maxn];
ll X_(const Xl& a,const Xl& b) {return a.x*b.y-a.y*b.x;}
ll D_(const Xl& a,const Xl& b) {return a.x*b.x+a.y*b.y;}
bool onit(const Xl& o,const Xl& a,const Xl& b) {
if(X_(o-a,b-a)!=0) return 0;
if(D_(o-a,b-a)<0) return 0;
if(D_(o-b,a-b)<0) return 0;
return 1;
}
int main() {
freopen("android.in","r",stdin);
freopen("android.out","w",stdout);
read(n); W=(1<<n)-1;
ll x,y;
For(i,1,n) {
read(x); read(y);
p[i]=Xl(x,y);
}
For(i,1,n) For(j,i+1,n) {
For(k,1,n) if(k!=i&&k!=j)
if(onit(p[k],p[i],p[j])) nd[i][j]|=(1<<k-1);
nd[j][i]=nd[i][j];
}
For(i,1,W) cnt[i]=cnt[i-(i&-i)]+1;
For(i,1,n) f[1<<i-1][i]=1;
For(i,0,W) For(j,1,n) if(f[i][j]%=mod) {
For(k,1,n) if((i&(1<<k-1))==0&&(nd[j][k]&i)==nd[j][k])
f[i|(1<<k-1)][k]+=f[i][j];
}
For(i,0,W) if(cnt[i]>3) For(j,1,n) ans+=f[i][j];
printf("%lld\n",ans%mod);
// cerr<<clock()<<"\n";
return 0;
}
D2T2



家里有九连环,总觉得自己手速太慢,思考过这个问题,但是当时没思考出来(毕竟当时还没学OI)。
打表可知:
i为奇数的时候,f[i]=f[i-1]<<1|1
i为偶数的时候,f[i]=f[i-1]<<1
需要高精,似乎Achen被卡常了
我场上写输出的时候0的个数不太对,WA惨了
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=2000+7,maxt=103;
ll Td,n,now[maxn],ans[maxt][maxn],W=1e18,q[maxt];
char cc; ll ff;
template<typename T>void read(T& aa) {
aa=0;cc=getchar();ff=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
aa*=ff;
}
void qc() {
For(i,1,now[0]) now[i]<<=1;
For(i,1,now[0]) while(now[i]>=W) now[i]-=W,now[i+1]++;
if(now[now[0]+1]) now[0]++;
}
void qj() {
now[1]++;
ll pos=1;
while(now[pos]>=W) now[pos]-=W,now[++pos]++;
now[0]=max(now[0],pos);
}
void print_ans(ll* now) {
printf("%lld",now[now[0]]);
Rep(i,now[0]-1,1) printf("%018lld",now[i]);
printf("\n");
}
int main() {
freopen("baguenaudier.in","r",stdin);
freopen("baguenaudier.out","w",stdout);
read(Td);
For(i,1,Td) read(q[i]),q[0]=max(q[0],q[i]);
n=q[0];
memset(now,0,sizeof(now));
now[0]=1;
For(i,1,n) {
qc();
if(i&1) qj();
For(j,1,Td) if(q[j]==i) memcpy(ans[j],now,sizeof(now));
}
For(i,1,Td) print_ans(ans[i]);
// cerr<<clock()<<"\n";
return 0;
}
D2T3


莫队
一开始以为每次查询的k互不相同,要动态维护线性基,所以写了一个回滚莫队……
然后懒得改成普通莫队了
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=5e5+7;
ll n,m,K,a[maxn],ans[maxn],sz;
char cc; ll ff;
template<typename T>void read(T& aa) {
aa=0;cc=getchar();ff=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
aa*=ff;
}
int id(int x) {return x/sz;}
struct Ask{
int l,r,qid;
Ask(){}
Ask(int l,int r,int qid):l(l),r(r),qid(qid){}
bool operator < (const Ask& b) const{return id(l)==id(b.l)? r<b.r:l<b.l;}
}ask[maxn];
int tot;
ll sum[maxn],now,nw;
int mdf[maxn],cnt;
void clear() {
while(cnt) --sum[mdf[cnt--]];
now-=nw; nw=0;
}
void clear_all() {
memset(sum,0,sizeof(sum));
cnt=now=nw=0;
}
void insert(int x,int o) {
if(o) mdf[++cnt]=x,nw+=sum[x^K];
now+=sum[x^K];
++sum[x];
}
void solve(int l,int r,int p) {
For(i,l,r) insert(a[i],1);
ans[p]=now;
clear();
}
int main() {
freopen("xor.in","r",stdin);
freopen("xor.out","w",stdout);
read(n); read(m); read(K);
For(i,1,n) read(a[i]),a[i]^=a[i-1];
sz=sqrt(n);
int l,r;
For(i,1,m) {
read(l); read(r);
if(r-l<=2*sz) solve(l-1,r,i);
else ask[++tot]=Ask(l-1,r,i);
}
sort(ask+1,ask+tot+1);
int last=1,ld,rd;
For(i,1,tot) {
if(i==tot||id(ask[i].l)!=id(ask[i+1].l)) {
clear_all();
ld=rd=(id(ask[i].l)+1)*sz-1;
For(j,last,i) {
clear();
For(k,rd+1,ask[j].r) insert(a[k],0);
rd=ask[j].r;
Rep(k,ld,ask[j].l) insert(a[k],1);
ans[ask[j].qid]=now;
}
last=i+1;
}
}
For(i,1,m) printf("%lld\n",ans[i]);
return 0;
}
弱者就是会被欺负呀

浙公网安备 33010602011771号