1. 程式人生 > >20180620小測

20180620小測

stp init ide 如果 tree count ret display b-

為什麽這麽多原題......

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



20180620小測