20180620小测

为什么这么多原题......

T1:


这题我做过,「BZOJ2568: 比特集合」了解一下,此题终结。
代码:

 1 #pragma GCC optimize("Ofast")
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<tr1/unordered_set>
 5 #include<cctype>
 6 typedef long long int lli;
 7 using namespace std;
 8 using namespace tr1;
 9 const int maxk=18;
10 const lli lim=(1<<18)+5;
11 
12 struct BinaryIndexTree {
13     int dat[lim];
14     #define lowbit(x) (x&-x)
15     inline void update(int pos,const int &x) {
16         while( pos < lim ) dat[pos] += x , pos += lowbit(pos);
17     }
18     inline int query(int pos) {
19         int ret = 0;
20         while(pos) ret += dat[pos] , pos -= lowbit(pos);
21         return ret;
22     }
23 }bit[maxk];
24 
25 lli sum;
26 unordered_multiset<lli> app;
27 
28 inline void update(lli x,const int &t) {
29     for(int i=0;i<maxk;i++) bit[i].update( ( x & ((1<<(i+1))-1) ) + 1 , t );
30 }
31 inline int query(int x) {
32     int l = 1 << x , r = ( 1 << ( x + 1 ) ) - 1 , ret = 0;
33     ret += bit[x].query( min( lim - 1 , max( 0ll , r - ( sum & ((1<<(x+1))-1) ) + 1 ) ) );
34     ret -= bit[x].query( min( lim - 1 , max( 0ll , l - ( sum & ((1<<(x+1))-1) ) ) ) );
35     l |= 1 << ( x + 1 ) , r |= 1 << ( x + 1 );
36     ret += bit[x].query( min( lim - 1 , max( 0ll , r - ( sum & ((1<<(x+1))-1) ) + 1 ) ) );
37     ret -= bit[x].query( min( lim - 1 , max( 0ll , l - ( sum & ((1<<(x+1))-1) ) ) ) );
38     return ret;
39 }
40 
41 inline char nextchar() {
42     static const int BS = 1 << 21;
43     static char buf[BS],*st,*ed;
44     if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin);
45     return st == ed ? -1 : *st++;
46 }
47 inline int getint() {
48     int ret = 0 , ch , fix = 1;
49     while( !isdigit(ch=nextchar()) ) fix = ch == '-' ? -fix : fix;
50     do ret = ret * 10 + ch - '0'; while( isdigit(ch=nextchar()) );
51     return ret * fix;
52 }
53 
54 int main() {
55     static int n;
56     static lli x;
57     n = getint();
58     for(int i=1,o;i<=n;i++) {
59         o = getint() , x = getint();
60         if( o == 2 ) sum += x;
61         else if( o == 0 ) x -= sum , app.insert(x) , update(x,1);
62         else if( o == 1 ) x -= sum , update(x,-(signed)app.count(x)) , app.erase(x);
63         else printf("%d\n",query(x));
64     }
65     return 0;
66 }
View Code

 


T2:


这题我做过,「BZOJ5332: [Sdoi2018]旧试题」了解一下,此题终结。
代码:

 1 #pragma GCC optimize("Ofast")
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<cctype>
 7 typedef long long int lli;
 8 const int maxn=1e5+1e2,lim=1e5;
 9 const lli mod = ( 1ll << 32 );
10 
11 struct Edge { int tar,lcm; };
12 struct Node { int u,v,w; } ns[maxn*21];
13 int mu[maxn];
14 lli fa[maxn],fb[maxn],fc[maxn],ans;
15 int deg[maxn],mem[maxn];
16 int a,b,c,n,m,ecnt;
17 std::vector<Edge> es[maxn];
18 
19 inline int gcd(int x,int y) {
20     register int t;
21     while( t = x % y ) x = y , y = t;
22     return y;
23 }
24 inline void sieve() {
25     static int prime[maxn/10],cnt;
26     static bool vis[maxn];
27     mu[1] = 1;
28     for(int i=2;i<=lim;i++) {
29         if( !vis[i] ) prime[++cnt] = i , mu[i] = -1;
30         for(int j=1;j<=cnt&&(lli)i*prime[j]<=lim;j++) {
31             const int tar = i * prime[j];
32             vis[tar] = 1;
33             if( i % prime[j] ) mu[tar] = -mu[i];
34             else break;
35         }
36     }
37 }
38  
39 inline void getf(lli* dst,int lim) {
40     for(int i=1;i<=lim;i++) for(int j=i;j<=lim;j+=i) dst[i] += lim / j;
41 }
42 inline void calc_single_point() {
43     for(int i=1;i<=m;i++) if( mu[i] ) ans += mu[i] * mu[i] * mu[i] * fa[i] * fb[i] * fc[i];
44 }
45 inline void pre_ring() {
46     for(int g=1;g<=n;g++) for(int i=1;i*g<=n;i++) if( mu[i*g] ) for(int j=i+1;(lli)i*j*g<=n;j++) if( mu[j*g] && gcd(i,j) == 1 ) {
47         const int u = i * g , v = j * g , w = i * j * g , pi = mu[u] * mu[u] * mu[v] , qi = mu[u] * mu[v] * mu[v];
48         if( w > n ) continue;
49         ans += pi * ( fa[u] * fb[w] * fc[w] + fa[w] * fb[u] * fc[w] + fa[w] * fb[w] * fc[u] );
50         ans += qi * ( fa[v] * fb[w] * fc[w] + fa[w] * fb[v] * fc[w] + fa[w] * fb[w] * fc[v] );
51         ++deg[u] , ++deg[v] , ns[++ecnt] = (Node){u,v,w};
52     }
53     for(int i=1;i<=ecnt;i++) {
54         if( deg[ns[i].u] < deg[ns[i].v] || ( deg[ns[i].u] == deg[ns[i].v] && ns[i].u < ns[i].v ) ) es[ns[i].u].push_back((Edge){ns[i].v,ns[i].w});
55         else es[ns[i].v].push_back((Edge){ns[i].u,ns[i].w});
56     }
57 }
58 inline void calc_ring() {
59     for(int i=1;i<=n;i++) {
60         for(unsigned J=0;J<es[i].size();J++) mem[es[i][J].tar] = es[i][J].lcm;
61         for(unsigned J=0;J<es[i].size();J++) {
62             const int j = es[i][J].tar;
63             for(unsigned K=0;K<es[j].size();K++) {
64                 const int k = es[j][K].tar , pi = mu[i] * mu[j] * mu[k];
65                 const int lij = es[i][J].lcm , ljk = es[j][K].lcm , lki = mem[k];
66                 if( !lki ) continue; // lcm(i,k) > n so i didn't record k .
67                 ans += pi * ( fa[lij] * fb[ljk] * fc[lki] + fa[lij] * fb[lki] * fc[ljk] + fa[ljk] * fb[lij] * fc[lki] + 
68                               fa[ljk] * fb[lki] * fc[lij] + fa[lki] * fb[lij] * fc[ljk] + fa[lki] * fb[ljk] * fc[lij] );
69             }
70         }
71         for(unsigned J=0;J<es[i].size();J++) mem[es[i][J].tar] = 0;
72     }
73 }
74  
75 inline void init() {
76     n = std::max( a , std::max( b , c ) ) , m = std::min( a , std::min( b , c ) ) , ans = 0;
77 }
78  
79 inline int getint() {
80     int ret = 0 , ch;
81     while( !isdigit(ch=getchar()) );
82     do ret = ret * 10 + ch - '0'; while( isdigit(ch=getchar()) );
83     return ret;
84 }
85  
86 int main() {
87     static int T;
88     a = getint() , b = getint() , c = getint() , init() , sieve() , getf(fa,a) , getf(fb,b) , getf(fc,c);
89     calc_single_point() , pre_ring() , calc_ring() , printf("%lld\n",ans%mod);
90     return 0;
91 }
View Code

 


T3:


这题,我......没做过。
这种期望一看就是假期望,其实就是统计贡献然后除总方案数。
于是我想到了一个暴力DP:
我们令f(i,j)表示i个不同的点分成j个联通块的方案数,我们有:

然后想了半天怎么优化,想不出来,10分弃疗。
正解根本不是这么做的......
首先《具体数学》告诉我们:

其中S(n,i)为第二类斯特林数,表示把n个点划分成i个不同的集合的方案数。
(考虑左边是n个不同球x个不同盒子随便放的方案数,右边先钦定用几个盒子,选出盒子并排列,把球分开然后放进去的方案数,正确性显然)
我们令f(i,j)表示i个点x次的贡献,如果分成了j个联通块,则贡献为下面的val,考虑贡献的组合意义(联通块间有序),我们得到f的转移和答案的计算公式:

其中g(i)表示g个点的联通块方案数,怎么求?「BZOJ3456: 城市规划」了解一下。
把组合数拆开,显然就是卷积了。最后是斯特林数的递推问题了:

注意一下初值,然后就能AC啦。
考场10分代码:

 1 #pragma GCC optimize("Ofast")
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 typedef long long int lli;
 7 using namespace std;
 8 const int maxn=512;
 9 const int mod=1004535809;
10 
11 inline int add(const int &x,const int &y) {
12     const int ret = x + y;
13     return ret >= mod ? ret - mod : ret;
14 }
15 inline int mul(const int &x,const int &y) {
16     return (lli) x * y % mod;
17 }
18 inline void adde(int &dst,const int &x) {
19     if( ( dst += x ) >= mod ) dst -= mod;
20 }
21 inline void sube(int &dst,const int &x) {
22     if( ( dst -= x ) < 0 ) dst += mod;
23 }
24 inline void mule(int &dst,const int &x) {
25     dst = (lli) dst * x % mod;
26 }
27 inline int fastpow(int base,int tim) {
28     int ret = 1;
29     while(tim) {
30         if( tim & 1 ) mule(ret,base);
31         if( tim >>= 1 ) mule(base,base);
32     }
33     return ret;
34 }
35 
36 int f[maxn][maxn],c[maxn][maxn],mem[maxn][17];
37 
38 int main() {
39     c[0][0] = 1;
40     for(int i=1;i<maxn;i++) {
41         c[i][0] = 1;
42         for(int j=1;j<=i;j++) c[i][j] = add(c[i-1][j-1],c[i-1][j]);
43     }
44     f[1][1] = 1;
45     for(int i=2;i<maxn;i++) {
46         f[i][i] = 1;
47         for(int j=i-1;j>=1;j--) {
48             for(int t=1;t<=i;t++) adde(f[i][j],mul(mul(f[t][1],c[i][t]),f[i-t][j-1]));
49             mule(f[i][j],fastpow(j,mod-2));
50         }
51         f[i][1] = fastpow(2,i*(i-1)>>1);
52         for(int j=2;j<=i;j++) sube(f[i][1],f[i][j]);
53     }
54     int t;
55     scanf("%d",&t) , memset(mem,-1,sizeof(mem));
56     while(t--) {
57         int n,k,ans=0;
58         scanf("%d%d",&n,&k);
59         if( ~mem[n][k] ) printf("%d\n",mem[n][k]);
60         else {
61             for(int i=1;i<=n;i++) adde(ans,mul(f[n][i],fastpow(i,k)));
62             mule(ans,fastpow(fastpow(2,n*(n-1)>>1),mod-2)) , printf("%d\n",mem[n][k]=ans);
63         }
64     }
65     return 0;
66 }
View Code

正解代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define debug cout
  6 typedef long long int lli;
  7 using namespace std;
  8 const int maxn=131073;
  9 const int mod=1004535809,G=3;
 10 
 11 inline int add(const int &x,const int &y) {
 12     const int ret = x + y;
 13     return ret >= mod ? ret - mod : ret;
 14 }
 15 inline int sub(const int &x,const int &y) {
 16     const int ret = x - y;
 17     return ret < 0 ? ret + mod : ret;
 18 }
 19 inline int mul(const int &x,const int &y) {
 20     return (lli) x * y % mod;
 21 }
 22 inline void adde(int &dst,const int &x) {
 23     if( ( dst += x ) >= mod ) dst -= mod;
 24 }
 25 inline void mule(int &dst,const int &x) {
 26     dst = (lli) dst * x % mod;
 27 }
 28 
 29 inline int fastpow(int base,int tim) {
 30     int ret = 1;
 31     while(tim) {
 32         if( tim & 1 ) mule(ret,base);
 33         if( tim >>= 1 ) mule(base,base);
 34     }
 35     return ret;
 36 }
 37 inline void NTT(int* dst,int n,int tpe) {
 38     for(int i=0,j=0;i<n;i++) {
 39         if( i < j ) swap(dst[i],dst[j]);
 40         for(int t=n>>1;(j^=t)<t;t>>=1) ;
 41     }
 42     for(int len=2,h=1;len<=n;len<<=1,h<<=1) {
 43         int per = fastpow(G,mod/len);
 44         if( !~tpe ) per = fastpow(per,mod-2);
 45         for(int st=0;st<n;st+=len) {
 46             int w = 1;
 47             for(int pos=0;pos<h;pos++) {
 48                 const int u = dst[st+pos] , v = mul(dst[st+pos+h],w);
 49                 dst[st+pos] = add(u,v) , dst[st+pos+h] = sub(u,v) , mule(w,per);
 50             }
 51         }
 52     }
 53     if( !~tpe ) {
 54         const int inv = fastpow(n,mod-2);
 55         for(int i=0;i<n;i++) mule(dst[i],inv);
 56     }
 57 }
 58 inline void INV(int* dst,const int* sou,int len) {
 59     static int tp[maxn];
 60     if( len == 1 ) return void( *dst = fastpow(*sou,mod-2) );
 61     INV(dst,sou,len>>1) , memcpy(tp,sou,len<<2) , memset(tp+len,0,len<<2);
 62     NTT(dst,len<<1,1) , NTT(tp,len<<1,1);
 63     for(int i=0;i<len<<1;i++) dst[i] = mul(dst[i],sub(2,mul(dst[i],tp[i])));
 64     NTT(dst,len<<1,-1) , memset(dst+len,0,len<<2);
 65 }
 66 
 67 int fac[maxn],inv[maxn],strl[21][21];
 68 inline int c(int n,int m) {
 69     return mul(fac[n],mul(inv[m],inv[n-m]));
 70 }
 71 
 72 int f[16][maxn],g[maxn],ways[maxn];
 73 const int len = 65536;
 74 
 75 namespace GetG {
 76     int b[maxn],c[maxn],invb[maxn];
 77     inline void work() {
 78         for(int i=0;i<len;i++) b[i] = mul(ways[i],inv[i]);
 79         for(int i=1;i<len;i++) c[i] = mul(ways[i],inv[i-1]);
 80         INV(invb,b,len) , NTT(invb,len<<1,1) , NTT(c,len<<1,1);
 81         for(int i=0;i<len<<1;i++) g[i] = mul(invb[i],c[i]);
 82         NTT(g,len<<1,-1) , g[0] = 0 , memset(g+len,0,len<<2);
 83         for(int i=1;i<len;i++) mule(g[i],fac[i-1]);
 84     }
 85 }
 86 
 87 namespace GetF {
 88     inline void work() {
 89         for(int i=1;i<len;i++) mule(g[i],inv[i]);
 90         for(int i=0;i<len;i++) f[0][i] = mul(ways[i],inv[i]);
 91         NTT(g,len<<1,1) , NTT(f[0],len<<1,1);
 92         for(int j=1;j<16;j++) {
 93             for(int i=0;i<len<<1;i++) f[j][i] = mul(f[j-1][i],g[i]);
 94             NTT(f[j],len<<1,-1) , memset(f[j]+len,0,len<<2) , NTT(f[j],len<<1,1);
 95         }
 96         for(int j=0;j<16;j++) {
 97             NTT(f[j],len<<1,-1);
 98             for(int i=0;i<len;i++) mule(f[j][i],fac[i]);
 99         }
100     }
101 }
102 
103 inline int getans(int n,int k) {
104     int ret = 0;
105     for(int i=0;i<=k;i++) adde(ret,mul(f[i][n],strl[k][i]));
106     return ret;
107 }
108 
109 inline void pre() {
110     *fac = 1; for(int i=1;i<len;i++) fac[i] = mul(fac[i-1],i);
111     inv[len-1] = fastpow(fac[len-1],mod-2); for(int i=len-1;i;i--) inv[i-1] = mul(inv[i],i);
112     for(int i=0;i<len;i++) ways[i] = fastpow(2,((lli)i*(i-1)>>1)%(mod-1));
113     strl[0][0] = 1;
114     for(int i=1;i<16;i++) {
115         strl[i][0] = 0;
116         for(int j=1;j<=i;j++) strl[i][j] = add(strl[i-1][j-1],mul(j,strl[i-1][j]));
117     }
118 }
119 
120 int main() {
121     static int t,n,k;
122     pre() , GetG::work() , GetF::work();
123     scanf("%d",&t);
124     while(t--) scanf("%d%d",&n,&k) , printf("%d\n",mul(getans(n,k),fastpow(ways[n],mod-2)));
125     return 0;
126 }
View Code

 



posted @ 2018-06-21 12:07  Cmd2001  阅读(244)  评论(0编辑  收藏  举报