2019正睿CSP-S模拟赛十连测day6

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 }
View Code

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 }
View Code

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 }
View Code
原文地址:https://www.cnblogs.com/C-S-X/p/11666035.html