开题,感觉 T1 很像 dky 讲过的一道中北大学 ACM 题,T3 一看就是随机化,具体不知道怎么做。
T1 sb 题,直接取当前最小的光滑数,把它乘一个质因子放入候选集。类似《蚯蚓》开 B 个队列即可,\(O(KB)\)。
T3 推出了四元二次方程组,不会解。。。考虑过枚举 \(s\)。
T2 貌似可以状压?两个质因子的情况特判就行了。
7.40 开始写 T1,最初 RE 了,加上判断队列为空就过了所有样例,看一眼才 8.00?想了想没什么可写挂挂的地方,时间又开了 \(2\)s,不管了。
T3 想了一会突然想到可以把 \(scale\times\sin(\theta),scale\times\cos(\theta)\) 看作两个变量,那就变成了四元一次方程。随便找两个点是正确的概率为 \(\frac 34\),跑个 \(30\) 次应该没问题,后来发现它没说无解怎么办,那直接 for(;;)
就行了。当时以为高斯消元的复杂度和 \(O(n)\) 检验是乘起来的,于是决定手解方程。推了两个未知数式子就很恶心了,准备以后再说。
写完过了小样例,测速发现 T 了,而且很久跑不出来,先去写了 T2 部分分,期间因为除以 \(0\) 和质因子大于 \(\sqrt n\) 死过
回来看 T3,还是跑不出来,怀疑假了。重拿一张草稿纸完整地过了一遍,确定没问题,开始卡常数,但还是过不去。当时加了一句剪枝:若从 \(\sin,\cos\) 算出的 \(\theta\) 不一样就跳过,删了就能跑出来,但没有细想。。。
rk4 100+12+60
T1 开 \(1s\) 都可以
T2 在 \(n\) 是质数时挂了,其他情况未知
T3 就是正解,WA 了。
rk1 杨卓凡 100+76+30
rk2 李嘉明 50+56+90
考场上思考方式还是有问题,T2 T3 都出现过错误的类似情况,但只想到了体现出来的部分,没有细想,这也是依赖 gdb 带来的后果。
6 月的时候算是减少了 gdb 的使用,但还是不够,尽量少调试,多肉眼观察。
思考的时候也要深入,不要局限在眼下,要联想到其他情况/算法
int k,b; const int p[] = {0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47}; queue<LL> que[16]; int find() { int res = 1; For(i,2,b) if( !que[i].empty() && que[i].front() < que[res].front() ) res = i; return res; } signed main() { // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); read(b,k); que[1].push(1); while( --k ) { int u = find(); LL val = que[u].front(); que[u].pop(); For(i,u,b) que[i].push(val*p[i]); // printf("@ %lld\n",val); } write(que[find()].front()); return iocl(); }
爆搜+记忆化就能过
状态是一个三元组:序列长度 \(l\),序列中有的质因子集合 \(s\),在不同数中出现过的质因子对(可能一对的两个质因子相同)集合 \(t\)。
解释一下 \(t\):不同数是为了避免同一个数标记了好几个质因子,质因子对是为了避免新加入数的质因子分布在前面不同的数中
说不太清楚,可以手模一下下面的序列(插入最后一个数):
\(6,6\) 合法
\(2,3,6\) 非法
\(6,2,3\) 合法
关于复杂度:\(n\) 的约数个数是 \(10^4\) 级别的,长度上界是 \(12\),而每个长度的状态数看似是 \(2^6\times2^{\binom62+6}\),但实际上约为 \(50000\)——官方sol。不会算,只会爆搜证明。
这份代码经过卡常复杂度瓶颈已经不在 dfs,而是分解质因数和预处理约数。
#define int unsigned #define LL ULL const int N = 1e6, mod = 1e9+7; LL n; int cnt=-1,m,po; LL p[7],c[7],d[N],state[N],id[7][7]; unordered_map<int,int> vis[14][1<<7]; int dfs(int l,int s,LL t) { if( vis[l][s][t] ) return vis[l][s][t]; int res = 1; For(i,1,m) { LL tt = t; For(j,0,cnt) if( state[i] & (1<<j) ) For(k,j,cnt) if( state[i] & (1<<k) && (t & id[j][k]) ) goto TO; For(j,0,cnt) if( state[i] & (1<<j) ) For(k,0,cnt) if( s & (1<<k) ) tt |= id[j][k]; res += dfs(l+1,s|state[i],tt); if( res >= mod ) res -= mod; TO:; } return vis[l][s][t] = res; } signed main() { id[0][0]=1,id[0][1]=2,id[0][2]=4,id[0][3]=8,id[0][4]=16,id[0][5]=32, id[1][0]=2,id[1][1]=64,id[1][2]=128,id[1][3]=256,id[1][4]=512,id[1][5]=1024, id[2][0]=4,id[2][1]=128,id[2][2]=2048,id[2][3]=4096,id[2][4]=8192,id[2][5]=16384, id[3][0]=8,id[3][1]=256,id[3][2]=4096,id[3][3]=32768,id[3][4]=65536,id[3][5]=131072, id[4][0]=16,id[4][1]=512,id[4][2]=8192,id[4][3]=65536,id[4][4]=262144,id[4][5]=524288, id[5][0]=32,id[5][1]=1024,id[5][2]=16384,id[5][3]=131072,id[5][4]=524288,id[5][5]=1048576; read(n); for(LL i = 2; i*i <= n; ++i) if( !(n % i) ) { d[++m] = i; if( n/i != i ) d[++m] = n/i; } d[++m] = n; while( n > 1 ) { ++cnt; for(LL i = 2; i*i <= n; ++i) if( !(n % i) ) { p[cnt] = i; break; } if( !p[cnt] ) p[cnt] = n; for(; !(n % p[cnt]); n /= p[cnt]) ++c[cnt]; } For(i,1,m) For(j,0,cnt) if( !(d[i] % p[j]) ) state[i] |= 1<<j; write(dfs(0,0,0)-1); return iocl(); }
#include<bits/stdc++.h> using namespace std; #define uu unsigned #define scanf abc=scanf #define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout) #define forg(i,x) for(int i=fir[x];i;i=nxt[i]) int abc; typedef pair<int,int>pii; typedef long long ll; typedef uu long long ull; typedef vector<int>VI; inline int rd(int l,int r){return rand()%(r-l+1)+l;} const int mod=1e9+7; ll X;int m,v[7],n; int zd[64],U; bool cmp1(int x,int y){return zd[x]<zd[y];} struct jg{ int n,a[7]; bool operator<(const jg&b)const{if(n!=b.n)return n<b.n;for(int i=1;i<=n;++i)if(a[i]!=b.a[i])return a[i]<b.a[i];return 0;} void px(){sort(a+1,a+n+1,cmp1);} }oo[903]; int xl[7]; map<jg,int>mp; void dfs(int z=(1<<m)-1,int d=0){ if(!z){ jg k;k.n=d;for(int i=1;i<=d;++i)k.a[i]=xl[i]; oo[++n]=k;return; } int zz=z&-z; for(int i=z^zz;~i;--i){i&=z^zz;xl[d+1]=zz|i,dfs(z^(zz|i),d+1);} } ll dp[13][64][903],vv[64]; int gxh(int a[]){jg k;k.n=a[0];for(int i=1;i<=k.n;++i)k.a[i]=a[i];k.px();return assert(mp[k]),mp[k];} int to(int a[],int z,int zz){ static int b[7];int n=a[0],n1=0; for(int i=1;i<=n;++i){int t=a[i]&zz;if(t)b[++n1]=t;} int t=z&zz;if(t)b[++n1]=t; b[0]=n1;return gxh(b); } int main(){ scanf("%lld",&X); for(int i=0;i<64;++i)for(int j=5;~j;--j)if(i>>j&1)zd[i]=j; for(int i=2;1ll*i*i<=X;++i)if(X%i==0){ int c=0;while(X%i==0)X/=i,++c; v[m++]=c; } if(X>1)v[m++]=1; U=(1<<m),--U; for(int i=0;i<(1<<m);++i)dfs(i); for(int i=1;i<=n;++i)mp[oo[i]]=i; for(int i=1;i<=n;++i){ jg o=oo[i]; xl[0]=o.n;for(int j=1;j<=o.n;++j)xl[j]=o.a[j]; // cout<<gxh(xl)<<endl; assert(gxh(xl)); } // return 3; dp[0][0][1]=1; ll ans=0; vv[0]=1;for(int i=1;i<=U;++i){vv[i]=1;for(int j=0;j<m;++j)if(i>>j&1)vv[i]=vv[i]*v[j]%mod;} for(int t=0;t<=m*2;++t)for(int j=0;j<(1<<m);++j)for(int k=1;k<=n;++k)if(dp[t][j][k]){ ans+=dp[t][j][k]; jg o=oo[k];xl[0]=o.n;for(int i=1;i<=o.n;++i)xl[i]=o.a[i]; for(int z=1;z<(1<<m);++z)if((z&j)==0){ assert(vv[z]); int c=0,zz=0;for(int i=1;i<=o.n;++i)if(z&xl[i])++c; for(int i=1;i<=o.n;++i)zz|=z&xl[i]; if(c<=1)(dp[t+1][j|zz][to(xl,z,U^zz)]+=dp[t][j][k]*vv[z])%=mod; } } --ans; ans=(ans%mod+mod)%mod;printf("%lld\n",ans); return 0; }
只考虑一个 \(2\pi\) 范围。考场做法的问题是 \(\sin,\cos\) 会确定唯一的 \(\theta\),但如果只用 asin
算的话有两个 \(\theta\) 都满足,因此有 \(\frac 12\) 的概率 WA。应该在算出 \(\theta\) 后检验一下 \(\cos\) 是否满足,不满足则乘 \(-1\)(高中三角函数知识)
mt19937 mt(time(0)); const int N = 1e5+5; int n; struct Node { double sx,sy,tx,ty; } p[N]; #define sx(x) p[x].sx #define sy(x) p[x].sy #define tx(x) p[x].tx #define ty(x) p[x].ty const double eps = 1e-6, pi = acos(-1); double s,th,dx,dy,a,b,f[6][6]; map<PII,bool> vis; int rnd() { return mt()%n+1; } bool equ(double x,double y) { return fabs(x-y) < eps; } void work(int x,int y) { f[1][1]=-sy(x),f[1][2]=sx(x),f[1][3]=1,f[1][4]=0,f[1][5]=tx(x), f[2][1]=sx(x),f[2][2]=sy(x),f[2][3]=0,f[2][4]=1,f[2][5]=ty(x), f[3][1]=-sy(y),f[3][2]=sx(y),f[3][3]=1,f[3][4]=0,f[3][5]=tx(y), f[4][1]=sx(y),f[4][2]=sy(y),f[4][3]=0,f[4][4]=1,f[4][5]=ty(y); For(i,1,4) { int p = i; if( i < 4 ) { if( fabs(f[4][i]) > fabs(f[p][i])+eps ) p = 4; if( i < 3 ) { if( fabs(f[3][i]) > fabs(f[p][i])+eps ) p = 3; if( i < 2 ) if( fabs(f[2][i]) > fabs(f[p][i])+eps ) p = 2; } } if( p != i ) swap(f[i],f[p]); f[i][5] /= f[i][i], f[i][4] /= f[i][i]; if( i <= 3 ) { f[i][3] /= f[i][i]; if( i <= 2 ) { f[i][2] /= f[i][i]; if( i <= 1 ) f[i][1] /= f[i][i]; } } if( i != 1 ) rFor(k,5,i) f[1][k] -= f[1][i] * f[i][k]; if( i != 2 ) rFor(k,5,i) f[2][k] -= f[2][i] * f[i][k]; if( i != 3 ) rFor(k,5,i) f[3][k] -= f[3][i] * f[i][k]; if( i != 4 ) rFor(k,5,i) f[4][k] -= f[4][i] * f[i][k]; } a = f[1][5], b = f[2][5], dx = f[3][5], dy = f[4][5]; s = sqrt(a*a+b*b), th = acos(b/s); if( !equ(sin(th)*s,a) ) th = -th; } signed main() { // printf("%.1lf\n\n",sin(0)); // freopen("a.in","r",stdin); // freopen("c1.out","w",stdout); scanf("%d",&n); For(i,1,n) scanf("%lf%lf%lf%lf",&sx(i),&sy(i),&tx(i),&ty(i)); shuffle(p+1,p+n+1,mt); for(int i,j;;) { do { i = rnd(), j = rnd(); } while( vis.count(MP(i,j)) ); vis[MP(i,j)] = vis[MP(j,i)] = 1; work(i,j); // th = 2.687435, s = 3.306753, dx = 2580.976362, dy = 2063.148692; if( s < -eps || 10+eps < s ) continue; int ok = 0, k; for(k = 1; k+5 <= n; k += 6) { if( equ(-a*sy(k)+b*sx(k)+dx,tx(k)) && equ(a*sx(k)+b*sy(k)+dy,ty(k)) ) ++ok; if( equ(-a*sy(k+1)+b*sx(k+1)+dx,tx(k+1)) && equ(a*sx(k+1)+b*sy(k+1)+dy,ty(k+1)) ) ++ok; if( equ(-a*sy(k+2)+b*sx(k+2)+dx,tx(k+2)) && equ(a*sx(k+2)+b*sy(k+2)+dy,ty(k+2)) ) ++ok; if( equ(-a*sy(k+3)+b*sx(k+3)+dx,tx(k+3)) && equ(a*sx(k+3)+b*sy(k+3)+dy,ty(k+3)) ) ++ok; if( equ(-a*sy(k+4)+b*sx(k+4)+dx,tx(k+4)) && equ(a*sx(k+4)+b*sy(k+4)+dy,ty(k+4)) ) ++ok; if( equ(-a*sy(k+5)+b*sx(k+5)+dx,tx(k+5)) && equ(a*sx(k+5)+b*sy(k+5)+dy,ty(k+5)) ) ++ok; } for(; k <= n; ++k) if( equ(-a*sy(k)+b*sx(k)+dx,tx(k)) && !equ(a*sx(k)+b*sy(k)+dy,ty(k)) ) ++ok; if( ok < (n+1)/2 ) continue; // printf("@ %.3lf %.3lf\n",a,b); printf("%.12lf\n%.12lf\n%.12lf %.12lf",th,s,dx,dy); return 0; } }