• [考试反思]1023csp-s模拟测试84:精妙


    一套很奇怪的题。单调性+神仙dp/搜索+随机化。

    但是说实在的,思路都很不错。

    考场上显然乱搞没什么好说的。

    虽说T2剪枝打错变量名掉了20分。。。

    T1:Smooth

    暴力各有不同,最暴力的想法就是往队列里不断扔。

    有的元素会被扔多次导致队列元素过多。

    像线性筛一样,从大到小枚举质因子,保证每个数只会被最大的质因子筛掉。

     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
    ",q.top());
    17 }
    T80

    像蚯蚓一样,加入队列有单调性,所以不用优先队列。

    开b个队列,每个队列i里存最大质因子是pi的数。

     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
    ",pop_push());
    20 }
    View Code

    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
    ",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
    ",sch(1)-1);
    27 }
    T74

    %%%ParisB的Six的状态定义。

    首先我们可以发现,每个质因子的第一次被加入,至多会分6批。

    我们考虑加入一个数的限制。

    如果某一种因子已经被两个数包含,你还含有这个因子,就不合法。

    如果你含有两个因子A和B,A和B被加入不在同一个数里(就是我上面说的“6批”),那么不合法。

    如果在同一批里,那么你就只与那一批的一个数冲突,还是合法的。

    所以你就记录一下每一个因子是在第几批加入的。8进制压位。

    0:未被加入。

    1~6:被在第1~6批加入。

    7:已经被加入2次。

    然后对于每一种状态,枚举$2^6$种可能的转移,不合法的情况只有上面2种。

    总复杂度$2^{18} imes 2^6 imes 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
    ",ans-1);
    32 }
    825B。快去%ParisB

    T3:Walker

    变化完之后的最终坐标是$(scale cos heta x - scale  sin heta y +d_x,scale sin heta x + scale cos heta y +d_y)$

    我们把$scale sin heta$和$scale cos heta$看做两个单独的变量,叫$a,b$吧

    然后我们随便带两组数据进去就能解出$a,b,d_x,d_y$这四个变量

    根据$sin^2 heta +cos^2 heta=1$,得到$a^2+b^2=scale^2$

    所以我们就解出了$scale$,同时也就解出了$sin heta$和$cos heta$

    然后问题在于怎么解出$ heta$。方法很多,我说一个。

    根据$frac{sin heta}{cos heta}=tan heta$我们能知道$tan$值,利用$atan$函数得到一个$ heta$值。

    然后我们再用$sin$函数算一下这个$ heta$的正弦值和上面那个$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
    %.18lf
    %.18lf %.18lf
    ",theta,scale,X,Y),0;
    33     }
    34 }
    View Code
  • 相关阅读:
    .NET定时任务执行管理器开源组件–FluentScheduler
    ASP.NET MVC 使用 FluentScheduler 定时器计划任务
    Windows 2008 IIS7.5中创建独立账号的FTP站点图文教程
    除非Microsoft FTP 服务(FTPSVC)正在运行,否则无法启动FTP站点。服务目前已停止
    Web API--自定义异常结果的处理
    C#怎么遍历一个对象里面的全部属性?
    WebApi 接口参数不再困惑:传参详解
    C#进阶系列——WebApi 接口测试工具:WebApiTestClient
    WebApi安全性 使用TOKEN+签名验证
    ASP.NET(C#) Web Api通过文件流下载文件到本地实例
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11730080.html
Copyright © 2020-2023  润新知