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



夜(よる)が明(あ)けて朝(あさ)が来(く)る
黑夜终去 黎明终来
星空(ほしぞら)が朝(あさ)に溶(と)けても
繁星即使融化于晨
君(きみ)の辉(かがや)きはわかるよ
我依可见君之光辉
思(おも)い出(で)を羽(は)ばたかせ
思念化为羽翼
君(きみ)の空(そら)へ舞(ま)い上(あ)がる
飞向星之所在

posted @ 2018-07-02 20:43  Cmd2001  阅读(473)  评论(0编辑  收藏  举报