• [考试反思]数学专题测试2:重铸


    这回真的是大众分了。肯定是不行的。。。联赛分已经比别人低了靠大众分不可能翻盘。

    还指望着省选翻盘的话,肯定不能止步于此。

    但是的确还是没有把能打的打满,T1被无良卡常了,最后才发现,来不及改了。

    T1是比较明显的,大概算了一下复杂度没问题就写了。然而并没有自测大数据。

    最后10分钟的时候想起来了,测了一下发现有点慢,疯狂加预处理,结果输出变了一慌没敢交。

    然而事实上原输出不对而新输出对。。。所以手里攥着20分硬是没交(又想起了联赛。。。)

    T2想骗分,故意开大模数尝试骗过$k=2$的点,然而出题人并没有留这种数据,于是浪费了很长时间分数没有变。

    T3一眼看上去这不是多点求值模板题吗?数据范围更小了时限更大了,但是模数不好要写MTT。

    开始回忆怎么构造。。。想了半天没想出来。。。弃了

    着手暴力瞬间想起luogu第一篇题解:可以秦九韶暴力展开实测可以AC。

    但是因为是乱搞所以没有仔细看,忘记了怎么写,发现复杂度主要在取模上但是不知道怎么减少次数。

    最后虽说常数的确比不少人小,但是还是一分都没有多。

    还是挺长记性的一次考试:

    不要认为哪个知识点没用指不定那天就抡上来一道模板题(只不过不是正解?)

    不要认为哪个小技巧没用指不定那天就抡上来一道卡常题(只不过比正解好写?)

    不要认为哪个数据点可以钻出题人说不留分可能真的就是不留分了

    而且一定要养成良好的卡常习惯,别的放一边,取模必须少!!!

    (实测T3我的暴力带取模75s去掉取模其余不变只剩下1.9s)

    T1:B

    题目大意:求值域为n长度为k的不下降且最大公约数为1的数列个数。

    $T le 5,k le 1000,n le 10^9,mod=10^9+7$

    反演一下就去掉了公约数的限制,整除分块一下杜教筛莫比乌斯函数前缀和就行。问题就是怎么快速求方案数。

    在数列开头加一个1在结尾加一个n就发现问题变成k次上涨可以为0恰好上涨n-1的方案数。挡板法,组合数。

    因为$k$很小所以组合数直接暴力乘,复杂度是$O(k)$的。理论可过。

    但是因为多测或什么的会被卡,小范围的需要预处理。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1000000007
     4 const int M=25000000;
     5 int p[M>>2],pc,mu[M],iv[1111],fac[M];char np[M];
     6 unordered_map<int,int>Mu;
     7 int MU(int x){
     8     if(x<M)return mu[x]; if(Mu.find(x)!=Mu.end())return Mu[x];
     9     int a=1;for(int i=2,N,l;N=x/i,i<=x;i=l)l=x/N+1,a-=(l-i)*MU(N);return a;
    10 }
    11 int qpow(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
    12 long long C(int n,int k){
    13     long long a=1;if(n<k)return 0;
    14     if(n<M)a=1ll*fac[n]*qpow(fac[n-k],mod-2)%mod;
    15     else for(int i=n;i>n-k;--i)a=a*i%mod;
    16     return a*iv[k]%mod;
    17 }
    18 main(){mu[1]=iv[1]=fac[1]=1,fac[0]=1;//freopen("1.in","r",stdin);
    19     for(int i=2;i<M;++i){
    20         if(!np[i])mu[p[++pc]=i]=-1;
    21         for(int j=1,x;j<=pc&&(x=p[j]*i)<M;++j)
    22             if(i%p[j])mu[x]=-mu[i],np[x]=1;
    23             else{np[x]=1;break;}
    24     }for(int i=2;i<M;++i)mu[i]+=mu[i-1],fac[i]=1ll*fac[i-1]*i%mod;
    25     for(int i=2;i<1001;++i)iv[i]=mod-mod/i*1ll*iv[mod%i]%mod;
    26     for(int i=2;i<1001;++i)iv[i]=1ll*iv[i]*iv[i-1]%mod;//puts("in");
    27     int t;cin>>t;while(t--){
    28         int n,k,a=0;cin>>n>>k;
    29         for(int i=1,l,N;N=n/i,i<=n;i=l+1)l=n/N,a=(a+(MU(l)-MU(i-1))*C(N+k-1,k))%mod;
    30         cout<<(a+mod)%mod<<endl;
    31     }
    32 }
    View Code

    T2:B君的回忆

    题目大意:$g(i)=g(i-1) imes 3 -g(i-2),g(0)=a,g(1)=b$求$g(g(g(g(...g(n)...)))) (mod p)$中$k$层嵌套。

    $T le 1000,a,b,n,ple 10^9,kle 100$

    可以说是结论题。没人会证明。

    对于$k=1$矩阵快速幂就可以了。

    对于$k=2$,内层的那个东西还是可以矩阵快速幂,但是。。。没有模数?项数貌似不可以直接取模。

    发现每一项都由前两项递推,还是在模意义下的,不难想到它有循环节,但是我只知道循环节长度小于$n^2$。

    结论来了,循环节长度为$O(n)$,$skyh$打表发现是$2n$及以下,所以其实不是很大。

    找循环节能想到什么?显然$BSGS$啊。

    然而对于原数列求循环节,不能单元素查找而要和前面的元素成对考虑,长度为$O(p)$还是很难弄。

    所以我们考虑找矩阵的循环节,你只要找到两个相同的矩阵就行。

    然后这题差不多就没了。然而这样可能会被卡常。

    因为模数不保证是质数(尤其是递归下去以后就很可能不是质数了),所以考虑把模数质因数分解。

    循环节长度自然是积性函数,然而实际上直接乘的确可能找到可行解但是却不一定最优,事实上取lcm即可。

    还可以再优化,对于一种质因子$p^k$它的循环节是$p$的循环节乘$p^{k-1}$。结论。原理不明。

    另外显而易见的找循环节可以记忆化。

    这样你就可以AC了。代码很好写。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 unordered_map<int,int>Mr;
     4 #define S 5689
     5 int mod,rA,rB;
     6 struct mtx{
     7     int b00,b01,b10,b11;
     8     int hsh(){return (b00+b01*137ll+b10*15797ll+b11*1797193ll)%S;}
     9     bool operator==(mtx y){return b00==y.b00&&b01==y.b01&&b10==y.b10&&b11==y.b11;}
    10     void operator*=(mtx y){
    11         int _00=(1ll*b00*y.b00+1ll*b01*y.b10)%mod,_01=(1ll*b00*y.b01+1ll*b01*y.b11)%mod,
    12             _10=(1ll*b10*y.b00+1ll*b11*y.b10)%mod,_11=(1ll*b11*y.b11+1ll*b10*y.b01)%mod;
    13         b00=_00;b01=_01;b10=_10;b11=_11;
    14     }
    15 }bs,B,rbs,I;
    16 struct Mtx{
    17     int a0,a1;
    18     void operator*=(mtx y){
    19         int _0=(1ll*a0*y.b00+1ll*a1*y.b10)%mod,_1=(1ll*a0*y.b01+1ll*a1*y.b11)%mod;
    20         a0=_0;a1=_1;
    21     }
    22 }ans,ra;
    23 struct Hash_Map{
    24     #define Q 1055335
    25     int fir[S],l[Q],c,v[Q];mtx m[Q];
    26     int&operator[](mtx x){
    27         int r=x.hsh();
    28         for(int i=fir[r];i;i=l[i])if(x==m[i])return v[i];
    29         l[++c]=fir[r];fir[r]=c;m[c]=x;return v[c]=0;
    30     }
    31 }M;
    32 int Find(int p){
    33     M.c=0;for(int i=0;i<S;++i)M.fir[i]=0;
    34     mod=p;int step=sqrt(p<<1)+1;
    35     rbs=bs=(mtx){0,mod-1,1,3};
    36     bs=B;B=I;
    37     for(int i=0;i<step;++i,B*=rbs)M[B]=i+1;
    38     bs=B;
    39     for(int i=1;i<step;++i,B*=bs)if(M[B])return i*step-M[B]+1;
    40 }
    41 int gcd(int x,int y){return y?gcd(y,x%y):x;}
    42 int find(int mo){
    43     if(Mr[mo])return Mr[mo];
    44     long long mp=mo,ans=1,ta;
    45     for(int i=2;i*i<=mp;++i)if(mp%i==0){
    46         mp/=i;ta=Find(i);
    47         while(mp%i==0)mp/=i,ta*=i;
    48         ans=ans*ta/gcd(ans,ta);
    49     }if(mp^1)ta=Find(mp),ans=ans*ta/gcd(ans,ta);
    50     return Mr[mo]=ans;
    51 }
    52 int g(int n,int k,int mo){//cerr<<n<<' '<<k<<' '<<mo<<endl;
    53     if(k==1){
    54         mod=mo;bs=(mtx){0,mod-1,1,3};ans=(Mtx){rA,rB};
    55         for(;n;n>>=1,bs*=bs)if(n&1)ans*=bs;
    56         return ans.a0;
    57     }int x=g(n,k-1,find(mo));
    58     mod=mo;bs=(mtx){0,mod-1,1,3};ans=(Mtx){rA,rB};
    59     for(;x;x>>=1,bs*=bs)if(x&1)ans*=bs;
    60     return ans.a0;
    61 }
    62 main(){I=(mtx){1,0,0,1};//freopen("17.in","r",stdin);freopen("my.out","w",stdout);
    63     int t,n,k;cin>>t;while(t-->0)cin>>rA>>rB>>n>>k>>mod,cout<<g(n,k,mod)<<endl;
    64 }
    View Code

    C:sanrd

    题目大意:$f(x)=sumlimits_{i=0}^{n-1} A_i x^i$。对于每个$x=bc^{4k}+dc^{2k}+e$求值。$k$取遍$[0,n-1]$

    $n le 60000,mod=1000003$。其余数据范围$le 10^6$

    首先可以暴力。秦九韶展开就可以AC了。

    其实就是减少取模次数,看代码就知道了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 unordered_map<int,int>Mr;
     4 #define S 5689
     5 int mod,rA,rB;
     6 struct mtx{
     7     int b00,b01,b10,b11;
     8     int hsh(){return (b00+b01*137ll+b10*15797ll+b11*1797193ll)%S;}
     9     bool operator==(mtx y){return b00==y.b00&&b01==y.b01&&b10==y.b10&&b11==y.b11;}
    10     void operator*=(mtx y){
    11         int _00=(1ll*b00*y.b00+1ll*b01*y.b10)%mod,_01=(1ll*b00*y.b01+1ll*b01*y.b11)%mod,
    12             _10=(1ll*b10*y.b00+1ll*b11*y.b10)%mod,_11=(1ll*b11*y.b11+1ll*b10*y.b01)%mod;
    13         b00=_00;b01=_01;b10=_10;b11=_11;
    14     }
    15 }bs,B,rbs,I;
    16 struct Mtx{
    17     int a0,a1;
    18     void operator*=(mtx y){
    19         int _0=(1ll*a0*y.b00+1ll*a1*y.b10)%mod,_1=(1ll*a0*y.b01+1ll*a1*y.b11)%mod;
    20         a0=_0;a1=_1;
    21     }
    22 }ans,ra;
    23 struct Hash_Map{
    24     #define Q 1055335
    25     int fir[S],l[Q],c,v[Q];mtx m[Q];
    26     int&operator[](mtx x){
    27         int r=x.hsh();
    28         for(int i=fir[r];i;i=l[i])if(x==m[i])return v[i];
    29         l[++c]=fir[r];fir[r]=c;m[c]=x;return v[c]=0;
    30     }
    31 }M;
    32 int Find(int p){
    33     M.c=0;for(int i=0;i<S;++i)M.fir[i]=0;
    34     mod=p;int step=sqrt(p<<1)+1;
    35     rbs=bs=(mtx){0,mod-1,1,3};
    36     bs=B;B=I;
    37     for(int i=0;i<step;++i,B*=rbs)M[B]=i+1;
    38     bs=B;
    39     for(int i=1;i<step;++i,B*=bs)if(M[B])return i*step-M[B]+1;
    40 }
    41 int gcd(int x,int y){return y?gcd(y,x%y):x;}
    42 int find(int mo){
    43     if(Mr[mo])return Mr[mo];
    44     long long mp=mo,ans=1,ta;
    45     for(int i=2;i*i<=mp;++i)if(mp%i==0){
    46         mp/=i;ta=Find(i);
    47         while(mp%i==0)mp/=i,ta*=i;
    48         ans=ans*ta/gcd(ans,ta);
    49     }if(mp^1)ta=Find(mp),ans=ans*ta/gcd(ans,ta);
    50     return Mr[mo]=ans;
    51 }
    52 int g(int n,int k,int mo){//cerr<<n<<' '<<k<<' '<<mo<<endl;
    53     if(k==1){
    54         mod=mo;bs=(mtx){0,mod-1,1,3};ans=(Mtx){rA,rB};
    55         for(;n;n>>=1,bs*=bs)if(n&1)ans*=bs;
    56         return ans.a0;
    57     }int x=g(n,k-1,find(mo));
    58     mod=mo;bs=(mtx){0,mod-1,1,3};ans=(Mtx){rA,rB};
    59     for(;x;x>>=1,bs*=bs)if(x&1)ans*=bs;
    60     return ans.a0;
    61 }
    62 main(){I=(mtx){1,0,0,1};//freopen("17.in","r",stdin);freopen("my.out","w",stdout);
    63     int t,n,k;cin>>t;while(t-->0)cin>>rA>>rB>>n>>k>>mod,cout<<g(n,k,mod)<<endl;
    64 }
    然而暴力还是不应该AC的必须特判啊

    说实在的这题模数不好,所以我以为正解不是多项式。然而只是需要MTT。。。

    然后这题也是个板子:多项式多点求值。前置是多项式除法,再前置是多项式求逆。

    多点求值就是构造我们要求值的点生成一个多项式:$prod (x-x_i)$

    分治。对于左边的那些点这个多项式的值为0,所以进行一次多项式取模,余数多项式就和A在右边的点值同余。

    同时也学会了怎么做4次FFT实现MTT。利用虚部做乘法分配率,凑一凑就优化到了5次,然后利用复数性质可以优化到4次。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1000003
     4 #define S 131072
     5 #define ll long long
     6 #define lc p<<1
     7 #define rc p<<1|1
     8 const double pi=acos(-1);
     9 struct cp{double r,i;
    10     cp operator+(cp x){return (cp){r+x.r,i+x.i};}
    11     cp operator-(cp x){return (cp){r-x.r,i-x.i};}
    12     cp operator*(cp x){return (cp){r*x.r-i*x.i,r*x.i+i*x.r};}
    13     void operator=(int x){r=x;i=0;}
    14 }w[2][19][S],x,y,a[S],b[S],c[S],d[S];
    15 int rev[S],ib[S],pr[S],X[S],RA[S],RB[S];const int s=(1<<15)-1;
    16 int pow(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
    17 void FFT(cp*a,int n,int O){
    18     for(int i=1;i<n;++i)if(rev[i]>i)swap(a[i],a[rev[i]]);
    19     for(int k=1,o=0;k<n;k<<=1,++o)for(int i=0;i<n;i+=k<<1)for(int j=i;j<i+k;++j)
    20         x=a[j],y=a[j+k]*w[O][o][j-i],a[j]=x+y,a[j+k]=x-y;
    21     if(!O)for(int i=0;i<n;++i)a[i].r/=n,a[i].i/=n;
    22 }
    23 ll r(double x){return (ll)(x+0.5)%mod;}
    24 void MTT(int*A,int*B,int*C,int n){
    25     for(int i=0;i<n;++i)a[i].r=A[i]>>15,a[i].i=A[i]&s,b[i].r=B[i]>>15,b[i].i=B[i]&s,rev[i]=rev[i>>1]>>1|(i&1?n>>1:0);
    26     FFT(a,n,1);FFT(b,n,1);
    27     for(int i=0;i<n;++i)c[i]=b[i],c[i].i*=-1;reverse(c+1,c+n);
    28     for(int i=0;i<n;++i)b[i]=b[i]*a[i],c[i]=c[i]*a[i];
    29     FFT(b,n,0);FFT(c,n,0);
    30     for(int i=0;i<n;++i)C[i]=((r((b[i].r+c[i].r)*0.5)<<30)+(r(b[i].i)<<15)+r((c[i].r-b[i].r)*0.5))%mod;
    31 }
    32 void inv(int*a,int*b,int n){
    33     if(n==1){b[0]=pow(a[0],mod-2);return;}
    34     inv(a,b,n+1>>1);int l=1;while(l<n<<1)l<<=1;
    35     for(int i=0;i<l;++i)RA[i]=i<n?a[i]:0,RB[i]=i<n+1>>1?b[i]:0;
    36     MTT(RA,RB,RA,l);MTT(RA,RB,RA,l);
    37     for(int i=0;i<l;++i)b[i]=(RB[i]+RB[i]-RA[i]+mod)%mod;
    38 }
    39 void re(int*a,int n){for(int i=0;i<<1<n;++i)swap(a[i],a[n-1-i]);}
    40 void MOD(int*a,int*b,int*r,int la,int lb){la++;lb++;
    41     re(a,la);re(b,lb);inv(b,ib,la-lb+1);
    42     int l=1;while(l<la<<1)l<<=1;MTT(a,ib,X,l);
    43     for(int i=la-lb+1;i<l;++i)ib[i]=0;
    44     re(X,la-lb+1);re(a,la);re(b,lb);
    45     for(int i=la-lb+1;i<l;++i)X[i]=0;
    46     MTT(X,b,pr,l);
    47     for(int i=0;i<lb-1;++i)r[i]=(a[i]-pr[i]+mod)%mod;
    48 }
    49 int A[S],Q[S],_[S],__[S],___[S],len[S<<1];vector<int>V[S<<1];
    50 void build(int l,int r,int p){len[p]=r-l+1;
    51     if(l==r){V[p].push_back(mod-Q[l]);V[p].push_back(1);len[p]=1;return;}
    52     int md=l+r>>1,le=1;while(le<=r-l+1)le<<=1;
    53     build(l,md,lc);build(md+1,r,rc);
    54     for(int i=0;i<le;++i)_[i]=__[i]=___[i]=0;
    55     for(int i=0;i<=len[lc];++i)_[i]=V[lc][i];
    56     for(int i=0;i<=len[rc];++i)__[i]=V[rc][i];
    57     MTT(_,__,___,le);for(int i=0;i<=r-l+1;++i)V[p].push_back(___[i]);
    58 }
    59 void solve(int l,int r,int*A,int p){
    60     if(r-l<625){
    61         for(int i=l,x;x=Q[i],i<=r;++i){
    62             long long ans=0,xp[26];int n=r-l+1;xp[0]=1;
    63             for(int i=1;i<26;++i)xp[i]=1ll*xp[i-1]*x%mod;
    64             for(int i=n/25*25;i>=0;i-=25){
    65                 ans=ans%mod*xp[25];
    66                 for(int j=0;j<25;++j)ans+=xp[j]*A[i+j];
    67             }printf("%lld
    ",ans%mod);
    68         }return;
    69     }
    70     int md=l+r>>1,le=1;while(le<=len[p])le<<=1;int rp[le<<1],mb[le<<1];
    71     for(int i=0;i<le<<1;++i)rp[i]=mb[i]=0;
    72     for(int i=0;i<=len[lc];++i)rp[i]=V[lc][i];
    73     MOD(A,rp,mb,len[p],len[lc]);
    74     solve(l,md,mb,lc);
    75     for(int i=0;i<le<<1;++i)rp[i]=mb[i]=0;
    76     for(int i=0;i<=len[rc];++i)rp[i]=V[rc][i];
    77     MOD(A,rp,mb,len[p],len[rc]);
    78     solve(md+1,r,mb,rc);
    79 }
    80 main(){
    81     register int n,b,c,d,e,r=1;
    82     cin>>n>>b>>c>>d>>e;c=1ll*c*c%mod;
    83     for(int i=0;1<<i<S;++i)for(int j=0;j<1<<i;++j)
    84         w[0][i][j]=(cp){cos(pi/(1<<i)*j),sin(-pi/(1<<i)*j)},
    85         w[1][i][j]=(cp){cos(pi/(1<<i)*j),sin(+pi/(1<<i)*j)};
    86     for(int i=0;i<n;++i)scanf("%d",&A[i]);
    87     for(register int i=0;i<n;++i)Q[i]=(1ll*b*r*r+1ll*d*r+e)%mod,r=1ll*r*c%mod;
    88     build(0,n-1,1);solve(0,n-1,A,1);
    89 }
    然而这不是正解。常数巨大险些跑不过暴力

    上面这个做法太过无脑暴力?复杂度为$O(nlog^2n)$

    正解复杂度要小一个$log$而且常数也小的多。

    需要大力推式子,我大概看了看明白了意思但是没有时间写出来了。

    然而NC不让粘他链接,而Dyyb粘了他的链接,于是我就粘Dyyb的链接好了,下次看的时候dfs一下就行。

  • 相关阅读:
    2020毕业设计选用4412开发板,实战教程,小成果不放过
    学习嵌入式有决心4412再送免费教程
    iTOP4412开发板can测试工具使用文档
    iTOP4412Ubuntu系统源码ubuntu没有声音的解决办法
    修身养性,为人处事100条
    用X++实现有规律分割的长字符串,分别提取(如逗号隔开)
    自定义Dialog中对数组的取值
    Common实现任何Form定位查询转到当前Form种过滤符合条件的数据区域
    用X++得到当前用户是否有某Security Key的权限级别,完整Job演示
    获取table中的系统字段信息
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12153015.html
Copyright © 2020-2023  润新知