一套很奇怪的題。單調性+神仙dp/搜索+隨機化。c++
可是說實在的,思路都很不錯。ide
考場上顯然亂搞沒什麼好說的。函數
雖然說T2剪枝打錯變量名掉了20分。。。spa
T1:Smooth3d
暴力各有不一樣,最暴力的想法就是往隊列裏不斷扔。code
有的元素會被扔屢次致使隊列元素過多。blog
像線性篩同樣,從大到小枚舉質因子,保證每一個數只會被最大的質因子篩掉。隊列
1 #include<cstdio> 2 #include<queue> 3 using namespace std; 4 priority_queue<long long,vector<long long>,greater<long long> >q; 5 const int P[16]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47}; 6 int main(){//freopen("ex_smooth1.in","r",stdin); 7 int k,b; 8 scanf("%d%d",&b,&k); 9 q.push(1); 10 k--; 11 while(k--){ 12 long long x=q.top();q.pop(); 13 for(int i=b;i;--i)if(x%P[i]==0){q.push(x*P[i]);break;} 14 else q.push(x*P[i]); 15 } 16 printf("%lld\n",q.top()); 17 }
像蚯蚓同樣,加入隊列有單調性,因此不用優先隊列。it
開b個隊列,每一個隊列i裏存最大質因子是pi的數。io
1 #include<cstdio> 2 #include<queue> 3 using namespace std; 4 queue<long long>q[16]; 5 const int P[16]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47}; 6 int b,k; 7 long long pop_push(){ 8 long long ans=q[1].front(),bp=1; 9 for(int i=2;i<=b;++i)if(q[i].front()<ans)ans=q[i].front(),bp=i; 10 q[bp].pop(); 11 for(int i=b;i>=bp;--i)q[i].push(ans*P[i]); 12 return ans; 13 } 14 int main(){ 15 scanf("%d%d",&b,&k); 16 for(int i=1;i<=b;++i)q[i].push(P[i]); 17 k-=2; 18 while(k--)pop_push(); 19 printf("%lld\n",pop_push()); 20 }
T2:Six
先說暴力?
搜啊,好像沒什麼好說的。
發現每次加入的數的影響只與它含有哪幾種質因子有關。
而後就能夠愉快的搜了。
1 #include<cstdio> 2 #define mod 1000000007 3 #define int long long 4 int t[7],knd,al[18];long long n,rate[65]; 5 int sch(int p){//if(p<=3)printf("%d\n",p); 6 int ans=1; 7 for(int i=1;i<1<<knd;++i){ 8 int cov=0; 9 for(int j=1;j<p;++j)if(i&al[j])cov++; 10 if(cov>1)continue; 11 al[p]=i; 12 ans=(ans+rate[i]*sch(p+1))%mod; 13 } 14 return ans; 15 } 16 main(){ 17 scanf("%lld",&n); 18 for(long long i=2;i*i<=n;++i)if(n%i==0){ 19 knd++; 20 while(n%i==0)n/=i,t[knd]++; 21 }if(n!=1)t[++knd]=1; 22 for(int i=1;i<1<<knd;++i){ 23 rate[i]=1; 24 for(int j=1;j<=knd;++j)if(i&1<<j-1)(rate[i]*=t[j])%=mod; 25 } 26 printf("%lld\n",sch(1)-1); 27 }
%%%ParisB的Six的狀態定義。
首先咱們能夠發現,每一個質因子的第一次被加入,至多會分6批。
咱們考慮加入一個數的限制。
若是某一種因子已經被兩個數包含,你還含有這個因子,就不合法。
若是你含有兩個因子A和B,A和B被加入不在同一個數裏(就是我上面說的「6批」),那麼不合法。
若是在同一批裏,那麼你就只與那一批的一個數衝突,仍是合法的。
因此你就記錄一下每個因子是在第幾批加入的。8進制壓位。
0:未被加入。
1~6:被在第1~6批加入。
7:已經被加入2次。
而後對於每一種狀態,枚舉$2^6$種可能的轉移,不合法的狀況只有上面2種。
總複雜度$2^{18} \times 2^6 \times 6$然而由於合法狀態只有2100種,因此最終的複雜度大約是1e6的。
代碼極短可是不易壓行(不然邏輯極其混亂)
適度的經常使用位運算宏定義能使代碼更加簡單而清晰
1 #include<cstdio> 2 #define mod 1000000007 3 #define s1 (k&1<<p-1) 4 #define s2 (j>>3*p-3&7) 5 int dp[266666],t[7],cnt,ans;long long n,rate[66]; 6 int main(){ 7 scanf("%lld",&n); 8 for(long long i=2;i*i<=n;++i)if(n%i==0){ 9 cnt++; 10 while(n%i==0)n/=i,t[cnt]++; 11 }if(n!=1)t[++cnt]=1; 12 for(int i=1;i<1<<cnt;++i){ 13 rate[i]=1; 14 for(int j=1;j<=cnt;++j)if(i&1<<j-1)rate[i]*=t[j]; 15 } 16 dp[0]=1; 17 for(int j=0;j<1<<cnt*3;++j)if(dp[j]){ 18 ans=(ans+dp[j])%mod; 19 for(int k=1;k<1<<cnt;++k){ 20 int x=0,ns=j,m=0; 21 for(int p=1;p<=cnt;++p)if(!s2&&s1){x=p;break;} 22 for(int p=1;p<=cnt;++p)if(s2&&s1) 23 if(s2==7)goto F; 24 else if(!m)m=s2; 25 else if(m!=s2)goto F; 26 for(int p=1;p<=cnt;++p)if(s1) 27 if(s2)ns|=7<<3*p-3; 28 else ns|=x<<3*p-3; 29 dp[ns]=(dp[ns]+dp[j]*rate[k])%mod; F:; 30 } 31 }printf("%d\n",ans-1); 32 }
T3:Walker
變化完以後的最終座標是$(scale \ cos \theta \ x - scale\ sin \theta \ y +d_x,scale \ sin \theta\ x + scale \ cos\theta \ y +d_y)$
咱們把$scale \ sin \theta$和$scale \ cos \theta$看作兩個單獨的變量,叫$a,b$吧
而後咱們隨便帶兩組數據進去就能解出$a,b,d_x,d_y$這四個變量
根據$sin^2\theta +cos^2\theta=1$,獲得$a^2+b^2=scale^2$
因此咱們就解出了$scale$,同時也就解出了$sin\theta$和$cos\theta$
而後問題在於怎麼解出$\theta$。方法不少,我說一個。
根據$\frac{sin\theta}{cos\theta}=tan\theta$咱們能知道$tan$值,利用$atan$函數獲得一個$\theta$值。
而後咱們再用$sin$函數算一下這個$\theta$的正弦值和上面那個$\frac{a}{scale}$是否一致。
若是一致,那麼就對了,不然加一個$\pi$,轉半圈就是了。(由於只根據$tan$獲得的角度值可能恰好是相反的)
咱們對於兩個座標求出的一組解拿去check,若是超過半數都是對的那麼就完事,不然繼續循環
由於有一半是正確的,因此你選出兩個正確座標的機率是$\frac{1}{4}$,不是很小,因此循環不會不少次。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ldb double 4 int n;ldb x[100005],y[100005],_x[100005],_y[100005],mxt[5][6]; 5 void Gauss(){ 6 for(int i=1;i<=4;++i){ 7 ldb mx=mxt[i][i];int mxp=i; 8 for(int j=i+1;j<=4;++j)if(fabs(mxt[j][i])>mx)mx=fabs(mxt[j][i]),mxp=j; 9 if(mxp!=i)for(int j=i;j<=5;++j)swap(mxt[i][j],mxt[mxp][j]); 10 for(int j=4;j>i;--j)for(int k=5;k>=i;--k)mxt[j][k]-=mxt[j][i]/mxt[i][i]*mxt[i][k]; 11 } 12 for(int i=4;i;--i)for(int j=i-1;j;--j)mxt[j][5]-=mxt[i][5]*mxt[j][i]/mxt[i][i]; 13 for(int i=4;i;--i)mxt[i][5]/=mxt[i][i]; 14 } 15 int main(){ 16 scanf("%d",&n);srand(time(0)); 17 for(int i=1;i<=n;++i)scanf("%lf%lf%lf%lf",&_x[i],&_y[i],&x[i],&y[i]); 18 while(1){ 19 int p1=rand()%n+1,p2=rand()%n+1,AC=0; 20 while(p1==p2)p2=rand()%n+1; 21 mxt[1][5]=x[p1];mxt[1][4]=0;mxt[1][3]=1;mxt[1][2]=-_y[p1];mxt[1][1]=+_x[p1]; 22 mxt[2][5]=y[p1];mxt[2][4]=1;mxt[2][3]=0;mxt[2][2]=+_x[p1];mxt[2][1]=+_y[p1]; 23 mxt[3][5]=x[p2];mxt[3][4]=0;mxt[3][3]=1;mxt[3][2]=-_y[p2];mxt[3][1]=+_x[p2]; 24 mxt[4][5]=y[p2];mxt[4][4]=1;mxt[4][3]=0;mxt[4][2]=+_x[p2];mxt[4][1]=+_y[p2]; 25 Gauss(); 26 ldb scale=mxt[1][5]*mxt[1][5]+mxt[2][5]*mxt[2][5];scale=sqrt(scale); 27 ldb cosine=mxt[1][5]/scale,sine=mxt[2][5]/scale,theta=atan(sine/cosine),X=mxt[3][5],Y=mxt[4][5]; 28 if(scale>10||scale<0)continue; 29 if(fabs(sin(theta)-sine)>1e-7)theta+=3.141592653589793238462643383279l; 30 if(theta<-1e-8)theta+=3.141592653589793238462643383279L*2; 31 for(int i=1;i<=n;++i)if(fabs(scale*cos(theta)*_x[i]-scale*sin(theta)*_y[i]+X-x[i])<1e-4&&fabs(scale*sin(theta)*_x[i]+scale*cos(theta)*_y[i]+Y-y[i])<1e-4)AC++; 32 if(AC>=n+1>>1)return printf("%.18lf\n%.18lf\n%.18lf %.18lf\n",theta,scale,X,Y),0; 33 } 34 }