1. 程式人生 > >20180702小測

20180702小測

hide max reg aps %d push != polya iostream

這場考試我其實並沒有參加......
因為一些奧妙重重的原因肚子疼到厭生,沒看完題就滾回家了......
馬上就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 int
mod=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 }
View Code



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小測