2019正睿CSP-S模拟赛十连测day6
100+80+20=200(rank=30)
各位dalao开场两三分钟就切了A题,我还是慢慢打表找规律才做出来。B题想到了正解,但是由于复杂度分析一头雾水,实现上面浪费了时间,挂了20分。C题直接没做。
A. Digit
- 发现一个y符合题意,当且仅当对于所有的 $x=0,1,...,y-1$ 都有 $x=x * P(mod y)$
- 显然$P-1$是一个合法的$y$,然后所有$P-1$的因数也合法,答案就是$P-1$的因数个数
1 #include<bits/stdc++.h> 2 #define FOR(i,a,b) for (register int i=(a);i<=(b);i++) 3 #define For(i,a,b) for (register int i=(a);i>=(b);i--) 4 #define mem(i,j) memset(i,j,sizeof(i)) 5 #define GO(u) for (register int j=f[u];j!=-1;j=nxt[j]) 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define MP make_pair 10 #define pii pair<int,int> 11 using namespace std; 12 typedef long long ll; 13 int P,ans; 14 inline int read() 15 { 16 int x=0,f=1; 17 char c=getchar(); 18 while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} 19 while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();} 20 return f*x; 21 } 22 inline void write(int x) 23 { 24 if (x<0) putchar('-'),x=-x; 25 if (x>9) write(x/10); 26 putchar(x%10+'0'); 27 return; 28 } 29 int main() 30 { 31 P=read(); 32 FOR(i,1,P-1) if ((P-1)%i==0) ans++; 33 write(ans); 34 return 0; 35 }
B. Gcd
- 设$i=d$时的答案为$ans_d$
- 枚举这个$d$,我们钦定所有的数都必需有因数$d$,我们统计出方案后并不能保证$gcd$就是$d$,还要将$ans_i$减去所有$ans_j,i|j$
- 我们在每一层枚举有多少个$a_i=b_i$的位置,随便用组合数统计一下就有了
- 实现上注意$cnt_i$的统计,以及快速幂不用每次都算的优化,就可以跑得很快乐
1 #include<bits/stdc++.h> 2 #define FOR(i,a,b) for (register int i=(a);i<=(b);i++) 3 #define For(i,a,b) for (register int i=(a);i>=(b);i--) 4 #define mem(i,j) memset(i,j,sizeof(i)) 5 #define GO(u) for (register int j=f[u];j!=-1;j=nxt[j]) 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define MP make_pair 10 #define pii pair<int,int> 11 using namespace std; 12 typedef long long ll; 13 const int N=4e5+5; 14 const int mod=998244353; 15 int n,m,k,a[N],ans[N],cnt[N]; 16 int fac[N],inv[N],mx; 17 inline int read() 18 { 19 int x=0,f=1; 20 char c=getchar(); 21 while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} 22 while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();} 23 return f*x; 24 } 25 inline void write(int x) 26 { 27 if (x<0) putchar('-'),x=-x; 28 if (x>9) write(x/10); 29 putchar(x%10+'0'); 30 return; 31 } 32 inline int qpow(int x,int y) 33 { 34 int ret=1; 35 while (y) 36 { 37 if (y&1) ret=1LL*ret*x%mod; 38 y>>=1; 39 x=1LL*x*x%mod; 40 } 41 return ret; 42 } 43 inline void init() 44 { 45 mx=max(n,m)+1; 46 fac[0]=1; 47 FOR(i,1,mx) fac[i]=1LL*fac[i-1]*i%mod; 48 inv[mx]=qpow(fac[mx],mod-2); 49 For(i,mx-1,0) inv[i]=1LL*inv[i+1]*(i+1)%mod; 50 return; 51 } 52 inline int C(int x,int y) 53 { 54 int ret=1LL*fac[x]*inv[y]%mod*inv[x-y]%mod; 55 return ret; 56 } 57 int main() 58 { 59 // freopen("data.in","r",stdin); 60 n=read(),m=read(),k=read(); 61 k=n-k; 62 FOR(i,1,n) a[i]=read(); 63 init(); 64 // FOR(i,1,n) for (register int j=1;j*j<=a[i];j++) if (a[i]%j==0) 65 // { 66 // cnt[j]++; 67 // if (j*j!=a[i]) cnt[a[i]/j]++; 68 // } 69 FOR(i,1,n) cnt[a[i]]++; 70 FOR(i,1,m) for (register int j=i+i;j<=m;j+=i) cnt[i]+=cnt[j]; 71 For(i,m,1) 72 { 73 int v=m/i; 74 if (i>m/2) ans[i]=(cnt[i]<=k); 75 else if (cnt[i]<=k) ans[i]=qpow(v,n); 76 else 77 { 78 int qp=qpow(v-1,cnt[i]),inv=qpow(v-1,mod-2); 79 FOR(j,0,k) 80 { 81 if (!(v-1)) break; 82 ans[i]=(1LL*ans[i]+1LL*C(cnt[i],j)*qp%mod)%mod; 83 qp=1LL*qp*inv%mod; 84 } 85 ans[i]=1LL*ans[i]*qpow(v,n-cnt[i])%mod; 86 } 87 for (register int j=i+i;j<=m;j+=i) ans[i]=(1LL*ans[i]-ans[j]+mod)%mod; 88 } 89 FOR(i,1,m) write(ans[i]),putchar(' '); 90 return 0; 91 }
C. Numbers
- 显然这个函数如果把它看作一个$2^{1012}$进制的数,不可能发生进位,所以函数的比大小等价于字典序比大小
- 长度不同的直接比长度,于是令$A_{i,j}$表示到第$i$位长度为$j$的本质不同子序列个数,由于我们需要本质不同,所以这里有一个关键的操作就是,相同的字符只能从它前面第一个转移,于是$A_i,j=sum_{k=lsa_i}^{i-1} A_{k,j-1}$,其中lsa表示第i位前面第一个等于$a_i$的位置
- 长度相同的也是一样的dp,主要思想还是哪个关键的操作,前缀和优化一下就是$O(n^2)$的简单dp了,我好菜
1 #include<bits/stdc++.h> 2 #define FOR(i,a,b) for (register int i=(a);i<=(b);i++) 3 #define For(i,a,b) for (register int i=(a);i>=(b);i--) 4 #define mem(i,j) memset(i,j,sizeof(i)) 5 #define GO(u) for (register int j=f[u];j!=-1;j=nxt[j]) 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define MP make_pair 10 #define pii pair<int,int> 11 using namespace std; 12 typedef long long ll; 13 const int N=5050; 14 const int mod=998244353; 15 int n,m,a[N],b[N],A[N][N],B[N][N],lsa[N],lsb[N],posa[N],posb[N],ans=0;//A,B表示i结尾,长度为j的本质不同子序列个数 16 int f[N][N],g[N][N];//f表示相等公共子序列个数,g表示A比B大子序列个数,都按本质不同来算 17 //AB第一维前缀和,fg双维前缀和 18 inline int read() 19 { 20 int x=0,f=1; 21 char c=getchar(); 22 while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} 23 while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();} 24 return f*x; 25 } 26 inline void write(int x) 27 { 28 if (x<0) putchar('-'),x=-x; 29 if (x>9) write(x/10); 30 putchar(x%10+'0'); 31 return; 32 } 33 inline void cal_different_length() 34 { 35 FOR(i,1,n) For(j,i-1,1) if (a[i]==a[j]) {lsa[i]=j;break;} 36 FOR(i,1,m) For(j,i-1,1) if (b[i]==b[j]) {lsb[i]=j;break;} 37 FOR(i,0,n) A[i][0]=1; 38 FOR(i,0,m) B[i][0]=1; 39 FOR(i,1,n) 40 { 41 FOR(j,1,i) 42 { 43 int now; 44 if (lsa[i]) now=((1LL*A[i-1][j-1]-A[lsa[i]-1][j-1])+mod)%mod; 45 else now=A[i-1][j-1]; 46 A[i][j]=(1LL*A[i][j]+now)%mod; 47 } 48 FOR(j,1,i) A[i][j]=(1LL*A[i][j]+A[i-1][j])%mod; 49 } 50 FOR(i,1,m) 51 { 52 FOR(j,1,i) 53 { 54 int now; 55 if (lsb[i]) now=((1LL*B[i-1][j-1]-B[lsb[i]-1][j-1])+mod)%mod; 56 else now=B[i-1][j-1]; 57 B[i][j]=(1LL*B[i][j]+now)%mod; 58 } 59 FOR(j,1,i) B[i][j]=(1LL*B[i][j]+B[i-1][j])%mod; 60 } 61 FOR(i,1,m) B[m][i]=(1LL*B[m][i]+B[m][i-1])%mod; 62 FOR(i,1,n) ans=(1LL*ans+1LL*A[n][i]*(B[m][min(i-1,m)]-1+mod)%mod)%mod; 63 return; 64 } 65 inline int query_f(int l1,int l2,int r1,int r2) 66 { 67 int ret=f[l2][r2]; 68 if (l1&&r1) ret=(1LL*ret+f[l1-1][r1-1])%mod; 69 if (l1) ret=(1LL*ret-f[l1-1][r2]+mod)%mod; 70 if (r1) ret=(1LL*ret-f[l2][r1-1]+mod)%mod; 71 return ret; 72 } 73 inline int query_g(int l1,int l2,int r1,int r2) 74 { 75 int ret=g[l2][r2]; 76 if (l1&&r1) ret=(1LL*ret+g[l1-1][r1-1])%mod; 77 if (l1) ret=(1LL*ret-g[l1-1][r2]+mod)%mod; 78 if (r1) ret=(1LL*ret-g[l2][r1-1]+mod)%mod; 79 return ret; 80 } 81 inline void cal_same_length() 82 { 83 FOR(i,0,n) FOR(j,0,m) f[i][j]=1,g[i][j]=0; 84 FOR(i,1,n) 85 { 86 FOR(j,1,m) 87 { 88 int now_f=0,now_g=0; 89 if (a[i]==b[j]) now_f=(1LL*now_f+query_f(lsa[i],i-1,lsb[j],j-1))%mod; 90 if (a[i]>b[j]) now_g=(1LL*now_g+query_f(lsa[i],i-1,lsb[j],j-1))%mod; 91 now_g=(1LL*now_g+query_g(lsa[i],i-1,lsb[j],j-1))%mod; 92 f[i][j]=(1LL*now_f+f[i-1][j]+f[i][j-1]-f[i-1][j-1]+mod)%mod; 93 g[i][j]=(1LL*now_g+g[i-1][j]+g[i][j-1]-g[i-1][j-1]+mod)%mod; 94 } 95 } 96 ans=(1LL*ans+g[n][m])%mod; 97 return; 98 } 99 int main() 100 { 101 // freopen("data.in","r",stdin); 102 n=read(),m=read(); 103 FOR(i,1,n) a[i]=read(); 104 FOR(i,1,m) b[i]=read(); 105 cal_different_length(); 106 cal_same_length(); 107 write(ans); 108 return 0; 109 }