20180702小測
這場考試我其實並沒有參加......
因為一些奧妙重重的原因肚子疼到厭生,沒看完題就滾回家了......
馬上就NOI了還是這種身體狀態,真是要完。
T1:
我們先把所有點雙聯通分量縮起來。
如果這個雙聯通分量只有一條邊,那麽方案數顯然是k;
如果這個雙聯通分量恰好是一個環,那麽方案數可以用polya定理計算;
否則,這個雙聯通分量的任意兩條邊可以互換顏色(自行構造一下就知道了),所以方案數只和某種顏色出現幾次有關,大力插板即可。
雙聯通分量的形態怎麽判?記錄點數和邊數判斷即可。
具體就是用vector存下來每個分量的每條邊,然後暴力數點即可。
(這裏吐槽一句求點雙聯通分量棧裏面壓點的都是邪教!你那麽做根本沒法統計返祖邊!)
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<cctype> 7 #define debug cout 8 typedef long long int lli; 9 using namespace std; 10 const int maxn=5e5+1e2,maxe=1e6+1e2; 11 const intView Codemod=1e9+7; 12 13 int inv[maxe]; 14 inline int mul(const int &x,const int &y) { 15 return (lli) x * y % mod; 16 } 17 inline void adde(int &dst,const int &x) { 18 if( ( dst += x ) >= mod ) dst -= mod; 19 } 20 inline void mule(int &dst,const int &x) { 21 dst = (lli) dst * x % mod;22 } 23 inline int fastpow(int base,int tim) { 24 int ret = 1; 25 while(tim) { 26 if( tim & 1 ) mule(ret,base); 27 if( tim >>= 1 ) mule(base,base); 28 } 29 return ret; 30 } 31 inline int c(int x,int y) { 32 int ret = 1; 33 for(int i=0;i<y;i++) mule(ret,x-i); 34 for(int i=1;i<=y;i++) mule(ret,inv[i]); 35 return ret; 36 } 37 inline int gcd(int x,int y) { 38 register int t; 39 while( t = x % y ) x = y , y = t; 40 return y; 41 } 42 43 int u[maxe],v[maxe]; 44 int s[maxn],t[maxe<<1],nxt[maxe<<1]; 45 int dfn[maxn],low[maxn],stk[maxe],top,fs; 46 vector<int> es[maxn<<1]; 47 bool vis[maxn]; 48 int n,m,k,ans=1; 49 50 inline void coredge(int from,int to) { 51 static int cnt = 1; 52 t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt; 53 } 54 inline void addedge(int a,int b) { 55 coredge(a,b) , coredge(b,a); 56 } 57 inline void dfs(int pos,int sou) { 58 static int dd; low[pos] = dfn[pos] = ++dd , vis[pos] = 1; 59 for(int at=s[pos];at;at=nxt[at]) if( at != ( sou ^ 1 ) ) { 60 if( !vis[t[at]] ) { 61 stk[++top] = at; 62 dfs(t[at],at) , low[pos] = min( low[pos] , low[t[at]] ); 63 if( low[t[at]] >= dfn[pos] ) { 64 int x; ++fs; 65 do es[fs].push_back((x=stk[top--])>>1); while( x != at ); 66 } 67 } else { 68 if( dfn[t[at]] < dfn[pos] ) stk[++top] = at; 69 low[pos] = min( low[pos] , dfn[t[at]] ); 70 } 71 } 72 } 73 inline void calc_ring(const vector<int> &vec) { 74 if( vec.size() == 1 ) return mule(ans,k); 75 int ps = 0; 76 for(unsigned i=0;i<vec.size();i++) { 77 if( !vis[u[vec[i]]] ) ps += vis[u[vec[i]]] = 1; 78 if( !vis[v[vec[i]]] ) ps += vis[v[vec[i]]] = 1; 79 } 80 for(unsigned i=0;i<vec.size();i++) vis[u[vec[i]]] = vis[v[vec[i]]] = 0; 81 if( ps == (signed)vec.size() ) { 82 int ret = 0; 83 for(int i=1;i<=ps;i++) adde(ret,fastpow(k,gcd(i,ps))); 84 mule(ret,inv[ps]) , mule(ans,ret); 85 } else mule(ans,c(k+vec.size()-1,vec.size())); 86 } 87 88 inline void init() { 89 inv[0] = inv[1] = 1; 90 for(int i=2;i<=m;i++) inv[i] = mul(mod-mod/i,inv[mod%i]); 91 } 92 93 inline int getint() { 94 int ret = 0 , ch; 95 while( !isdigit(ch=getchar()) ); 96 do ret = ret * 10 + ch - ‘0‘; while( isdigit(ch=getchar()) ); 97 return ret; 98 } 99 100 int main() { 101 n = getint() , m = getint() , k = getint() , init(); 102 for(int i=1;i<=m;i++) addedge(u[i]=getint(),v[i]=getint()); 103 for(int i=1;i<=n;i++) if( !vis[i] ) dfs(i,0); 104 memset(vis,0,sizeof(vis)); 105 for(int i=1;i<=fs;i++) calc_ring(es[i]); 106 printf("%d\n",ans); 107 return 0; 108 }
T2:
我會有下界的最小流!
等等,為什麽要按照上下界建圖呢?直接從欽定邊全選的狀態開始退流就行了,限制每個點能退的流量。水題!
然而SPJ還得自己改......
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cctype> 7 #define debug cout 8 using namespace std; 9 const int maxn=4e3+1e2,maxe=8e3+1e2; 10 const int inf=0x3f3f3f3f; 11 12 int u[maxn],v[maxn],deg[maxn]; 13 int n1,n2,m,mi=inf; 14 15 namespace NetworkFlow { 16 int s[maxn],t[maxe],nxt[maxe],f[maxe],cnt; 17 int dep[maxn],st,ed; 18 inline void coredge(int from,int to,int flow) { 19 t[++cnt] = to , f[cnt] = flow , nxt[cnt] = s[from] , s[from] = cnt; 20 } 21 inline void singledge(int from,int to,int flow) { 22 coredge(from,to,flow) , coredge(to,from,0); 23 } 24 inline bool bfs() { 25 memset(dep,-1,sizeof(dep)) , dep[st] = 0; 26 queue<int> q; q.push(st); 27 while( q.size() ) { 28 const int pos = q.front(); q.pop(); 29 for(int at=s[pos];at;at=nxt[at]) if( f[at] && !~dep[t[at]] ) { 30 dep[t[at]] = dep[pos] + 1 , q.push(t[at]); 31 } 32 } 33 return ~dep[ed]; 34 } 35 inline int dfs(int pos,int flow) { 36 if( pos == ed ) return flow; 37 int ret = 0 , now = 0; 38 for(int at=s[pos];at;at=nxt[at]) if( f[at] && dep[t[at]] > dep[pos] ) { 39 now = dfs(t[at],min(flow,f[at])) , ret += now , flow -= now , f[at] -= now , f[at^1] += now; 40 if( !flow ) return ret; 41 } 42 if( !ret ) dep[pos] = -1; 43 return ret; 44 } 45 inline int dinic() { 46 int ret = 0; 47 while( bfs() ) ret += dfs(st,inf); 48 return ret; 49 } 50 inline void reset() { 51 memset(s,0,sizeof(s)) , cnt = 1; 52 } 53 } 54 55 inline void build(int k) { 56 NetworkFlow::reset() , NetworkFlow::st = n1 + n2 + 1 , NetworkFlow::ed = n1 + n2 + 2; 57 for(int i=1;i<=m;i++) NetworkFlow::singledge(n1+v[i],u[i],1); 58 for(int i=1;i<=n1;i++) NetworkFlow::singledge(i,NetworkFlow::ed,deg[i]-k); 59 for(int i=n1+1;i<=n1+n2;i++) NetworkFlow::singledge(NetworkFlow::st,i,deg[i]-k); 60 } 61 inline void printans() { 62 static int seq[maxn],sql; sql = 0; 63 using namespace NetworkFlow; dinic(); 64 for(int i=1;i<=m;i++) if( f[i<<1] ) seq[++sql] = i; 65 sort(seq+1,seq+1+sql) , printf("%d ",sql); 66 for(int i=1;i<=sql;i++) printf("%d ",seq[i]); 67 putchar(‘\n‘); 68 } 69 70 inline int getint() { 71 int ret = 0 , ch; 72 while( !isdigit(ch=getchar()) ); 73 do ret = ret * 10 + ch - ‘0‘; while( isdigit(ch=getchar()) ); 74 return ret; 75 } 76 77 int main() { 78 n1 = getint() , n2 = getint() , m = getint(); 79 for(int i=1;i<=m;i++) ++deg[u[i]=getint()] , ++deg[n1+(v[i]=getint())]; 80 for(int i=1;i<=n1+n2;i++) mi = min( mi , deg[i] ); 81 for(int i=0;i<=mi;i++) build(i) , printans(); 82 return 0; 83 }View Code
SPJ:
1 #include<cstdio> 2 #define WA return puts("0"),0 3 #define AC return puts("4"),0 4 int n1,n2,m,u[2010],v[2010],md,ans[2010],deg[2][2010]; 5 bool used[2010]; 6 int full; 7 int main(int argc,char*argv[]){ 8 freopen(argv[1],"r",stdin); 9 scanf("%d%d%d",&n1,&n2,&m); 10 for(int i=0;i<m;i++)scanf("%d%d",u+i,v+i); 11 freopen(argv[3],"r",stdin); 12 md=-1; 13 while(scanf("%d",ans+(++md))==1){ 14 for(int i=ans[md];i--;)scanf("%*d"); 15 } 16 md--; 17 freopen(argv[2],"r",stdin); 18 freopen(argv[5],"w",stdout); 19 for(int i=0;i<=md;i++){ 20 int c; 21 if(scanf("%d",&c)!=1||c!=ans[i])WA; 22 for(int j=0;j<m;j++)used[j]=0; 23 for(int j=0;j<n1;j++)deg[0][j]=0; 24 for(int j=0;j<n2;j++)deg[1][j]=0; 25 while(c--){ 26 int x; 27 if(scanf("%d",&x)!=1||x<1||x>m||used[x-1])WA; 28 used[--x]=1; 29 deg[0][u[x]]++; 30 deg[1][v[x]]++; 31 } 32 for(int j=1;j<=n1;j++)if(deg[0][j]<i)WA; 33 for(int j=1;j<=n2;j++)if(deg[1][j]<i)WA; 34 } 35 AC; 36 }View Code
T3:
一臉不可做的樣子......
考慮對每個點統計覆蓋它的圓的貢獻。
我們先計算第一象限(含x軸)的答案,最後乘4在加上原點的貢獻即可。
考慮枚舉點的坐標,我們有:
(後面j是在枚舉能覆蓋這個點的圓,後面乘的是這個圓被統計的次數)
我們令:
顯然關於x的k次多項式的前綴和或有上界的後綴和都是一個關於x的k+1次多項式。所以這個s我們能拉格朗日插值。
那麽我們的公式能化為:
我們令:
就是一個把x當做常數,關於y的函數了。
我們理性分析一下,S(x)是關於x的3次多項式,那麽S(x^2+y^2)就是關於y的6次多項式,而這個東西是S(x^2+y^2)的前綴和,就是關於y的7次多項式嘍。
於是我們又能大力拉格朗日插值......
然後我們枚舉x,這題就做完了......復雜度O(sqrt(m)),常數巨大,最後一個點要7s......
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define debug cout 7 typedef long long int lli; 8 using namespace std; 9 const int mod=1e9+7; 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 sube(int &dst,const int &x) { 26 if( ( dst -= x ) < 0 ) dst += mod; 27 } 28 inline void mule(int &dst,const int &x) { 29 dst = (lli) dst * x % mod; 30 } 31 inline int fastpow(int base,int tim) { 32 int ret = 1; 33 while(tim) { 34 if( tim & 1 ) mule(ret,base); 35 if( tim >>= 1 ) mule(base,base); 36 } 37 return ret; 38 } 39 40 struct Interval { 41 int xs[11],ys[11],ps[11],cnt; 42 inline void insert(const int &x,const int &y) { 43 xs[++cnt] = x , ys[cnt] = y; 44 } 45 inline void init() { 46 for(int i=1;i<=cnt;i++) { 47 ps[i] = 1; 48 for(int j=1;j<=cnt;j++) if( j != i ) mule(ps[i],sub(xs[i],xs[j])); 49 ps[i] = fastpow(ps[i],mod-2); 50 } 51 } 52 inline int calc(const int &x) { 53 int ret = 0; 54 for(int i=1;i<=cnt;i++) { 55 int pi = 1; 56 for(int j=1;j<=cnt;j++) if( j != i ) mule(pi,sub(x,xs[j])); 57 adde(ret,mul(mul(pi,ps[i]),ys[i])); 58 } 59 return ret; 60 } 61 inline void reset() { 62 cnt = 0; 63 } 64 }s,f; 65 66 lli m; 67 int sq,ans; 68 69 inline void inits() { 70 const int m = ::m % mod; 71 for(int i=m,su;i>m-4;i--) { 72 su = 0; 73 for(int j=i;j<=m;j++) adde(su,mul(j,sub((m+1)%mod,j))); 74 s.insert(i,su); 75 } 76 s.init(); 77 } 78 inline void initf(int x) { 79 f.reset(); 80 for(int i=1,su=0;i<=8;i++) adde(su,s.calc(((lli)x*x+i*i)%mod)) , f.insert(i,su); 81 f.init(); 82 } 83 84 int main() { 85 scanf("%lld",&m) , inits() , sq = sqrt(m); 86 for(int i=0;i<=sq;i++) { 87 if( (lli) i * i + 8 * 8 <= m ) initf(i) , adde(ans,f.calc((lli)sqrt(m-(lli)i*i)%mod)); 88 else { 89 int t = sqrt(m-(lli)i*i); 90 for(int j=1;j<=t;j++) adde(ans,s.calc(((lli)i*i+j*j)%mod)); 91 } 92 } 93 mule(ans,4) , adde(ans,s.calc(0)) , printf("%d\n",ans); 94 return 0; 95 }View Code
夜(よる)が明(あ)けて朝(あさ)が來(く)る
黑夜終去 黎明終來
星空(ほしぞら)が朝(あさ)に溶(と)けても
繁星即使融化於晨
君(きみ)の輝(かがや)きはわかるよ
我依可見君之光輝
思(おも)い出(で)を羽(は)ばたかせ
思念化為羽翼
君(きみ)の空(そら)へ舞(ま)い上(あ)がる
飛向星之所在
20180702小測