第三周 9.14---9.20

---------9.14

 hdu 5446

中国剩余定理,lucas定理,快速乘法

四处抄的模板拼在一起的----------------

不说了--sad----

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 typedef long long LL;  
 8 LL n,m;  
 9 int k;
10 LL p[15],a[15];
11 
12 
13 inline LL mulmod(LL x,LL y,LL mod){
14     LL ret = 0;
15     if(y < 0) y = (y % mod + mod) % mod;
16     while(y){
17         if(y & 1) ret = (ret + x) % mod;
18         x = (x + x) % mod;
19         y >>= 1;
20     }
21     return ret;
22 }
23 
24 void extend_Euclid(LL a, LL b, LL &x, LL &y){
25     if(b == 0){  
26         x = 1;  
27         y = 0; 
28         return;
29     }
30     extend_Euclid(b, a % b, x, y);  
31     LL tmp = x;
32     x = y;
33     y = tmp - (a / b) * y;  
34 }  
35   
36 LL CRT(LL a[],LL m[],int n){  
37     LL M = 1;  
38     LL ans = 0;  
39     for(int i=1; i<=n; i++)  
40         M *= m[i];  
41     for(int i=1; i<=n; i++){  
42         LL x,y;  
43         LL Mi = M / m[i];  
44         extend_Euclid(Mi, m[i], x, y);  
45        // ans = (ans + Mi * x * a[i]) % M;
46         ans = (ans + mulmod(a[i],mulmod(Mi,x,M),M)) % M;  
47     }  
48     if(ans < 0) ans += M;  
49     return ans;
50 }
51   
52 LL quick_mod(LL a, LL b,LL p){  
53     LL ans = 1;  
54     a %= p;  
55     while(b){  
56         if(b & 1){  
57             ans = ans * a % p;  
58             b--;  
59         }  
60         b >>= 1;  
61         a = a * a % p;  
62     }  
63     return ans;  
64 }  
65   
66 LL C(LL n, LL m,LL p){  
67     if(m > n) return 0; 
68     if(m > n-m) m = n-m; 
69     LL ans = 1;  
70     for(int i=1; i<=m; i++)  {  
71         LL a = (n + i - m) % p;  
72         LL b = i % p;  
73         ans = mulmod(ans,mulmod(a,quick_mod(b, p-2,p),p),p);  
74     }  
75     return ans%p;
76 }  
77   
78 LL Lucas(LL n, LL m,LL p){  
79     if(m == 0) return 1;  
80     return mulmod(C(n % p, m % p,p),Lucas(n / p, m / p,p),p);
81 }  
82   
83 int main(){  
84     int T;  
85     scanf("%d", &T);  
86     while(T--){  
87         scanf("%I64d%I64d%I64d", &n, &m, &k);  
88         for(int i = 1;i <= k;i++) scanf("%I64d",&p[i]); 
89         
90         for(int i = 1;i <= k;i++) a[i] = Lucas(n,m,p[i]);
91         
92         LL res = CRT(a,p,k);
93         printf("%I64d\n",res);
94     }
95     return 0;  
96 }
View Code

 

hdu 5437

自己写的时候,还根据每次的时间去模拟,挫爆了,,,觉得应该T的,可是一直re

后来看题解,,才知道应该按人来模拟

然后看了题解之后还wa---

是因为m可以等于0,每次先把允许进来的时间处理成-1就可以了------

滚了-------

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<map>
 7 using namespace std;
 8 
 9 const int maxn = 150005;
10 
11 struct node1{
12     char s[305];
13     int v;
14     int id;
15     friend bool operator < (node1 n1,node1 n2){
16         if(n1.v != n2.v) return n1.v < n2.v;
17         return n1.id > n2.id;
18     }
19 }a[maxn];
20 
21 struct node2{
22     int t,p;
23 }b[maxn];
24 
25 int cmp(node2 n1,node2 n2){
26     return n1.t < n2.t;
27 }
28 
29 int n,m,Q;
30 int op[maxn],res[maxn];
31 
32 int main(){
33     int T;
34     scanf("%d",&T);
35     while(T--){
36         scanf("%d %d %d",&n,&m,&Q);
37         for(int i = 1;i <= n;i++){
38             scanf("%s %d",&a[i].s,&a[i].v);
39             a[i].id = i;
40         }
41         
42         b[1].t = -1;
43         for(int i = 1;i <= m;i++) scanf("%d %d",&b[i].t,&b[i].p);
44         
45         for(int i = 1;i <= Q;i++) scanf("%d",&op[i]);
46         
47         memset(res,0,sizeof(res));
48         sort(b+1,b+m+1,cmp);
49         priority_queue<node1> q;
50         
51         int pos = 1,cnt = 0;
52         for(int i = 1;i <= n;i++){
53             q.push(a[i]);
54             if(i == b[pos].t){
55                 for(int j = 1;j <= b[pos].p && !q.empty();j++){
56                     node1 u = q.top();q.pop();
57                     res[++cnt] = u.id;
58                 }
59                 pos++;
60             }
61         }
62         while(!q.empty()){
63             node1 u = q.top();q.pop();
64             res[++cnt] = u.id;
65         }
66         for(int i = 1;i < Q;i++) printf("%s ",a[res[op[i]]].s);
67         printf("%s\n",a[res[op[Q]]].s);
68     }
69     return 0;
70 }
View Code

 

---------9.15

还是觉得就抄个快速乘法的模板不好,于是滚去找了一下

搜到BC的33场的第二题就是快速幂加快速乘法---

当时根本没有去补题----不知道在干嘛-----

sad-----------

这题先需要推个公式

http://www.cnblogs.com/Opaser/p/4348988.html

然后快速乘法的原理感觉和快速幂差不多

x*y

就是y个x相加的情况

就类比 x ^y,即y个x相乘的情况

然后自己写的时候有两个地方出问题了

第一个是,n = 1的时候,想当然输出1了,但是因为p也可能是1,所以应该输出 n%p

第二个地方是,最后求出答案的时候,还要这样先加上一个mod,再取一次模(话说这样是为了防止负数么--)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 
 8 typedef long long LL;
 9 LL n,p;
10 
11 
12 inline LL mulmod(LL x,LL y,LL mod){
13     LL ret = 0;
14     if(y < 0) y = (y % mod + mod) % mod;
15     while(y){
16         if(y & 1) ret = (ret + x) % mod;
17         x = (x + x) % mod;
18         y >>= 1;
19     }
20     return ret;
21 }
22 
23 LL quick_mod(LL a, LL b,LL p){  
24     LL ans = 1;  
25     a %= p;  
26     while(b){  
27         if(b & 1){  
28             ans = mulmod(ans,a,p) % p;  
29             b--;  
30         }  
31         b >>= 1;  
32         a = mulmod(a,a,p) % p;  
33     }  
34     return ans;  
35 }  
36 
37 
38 void solve(){
39     if(n == 1){
40         printf("%I64d\n",n%p);
41         return;
42     }
43     printf("%I64d\n",(quick_mod(2,n,p)-2 + p)%p);
44 }
45 
46 int main(){
47     while(scanf("%I64d %I64d",&n,&p) != EOF){
48         solve();
49     }
50     return 0;
51 }
View Code

 

hdu 2191

多重背包

想起最开始学背包的时候,只学了完全背包,01背包

因为看不懂二进制那一块儿-------就一直没有去学-----

今天看了下,发现貌似略懂一点了

二进制的看的这个  http://blog.youkuaiyun.com/lyhvoyage/article/details/8545852

证明看得还有点不通

举个例子 17,从 1 到 17画了几下,发现是这样的

然后 代码看的这个  http://blog.youkuaiyun.com/acdreamers/article/details/8563283

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 
 8 const int maxn = 1005;
 9 int dp[maxn],n,m;
10 int c[maxn],w[maxn],num[maxn];
11 
12 void lingyi_pack(int cost,int weight,int m){
13     for(int i = m;i >= cost;i--) {
14         dp[i] = max(dp[i],dp[i-cost]+weight);
15     }
16 }
17 
18 void wanquan_pack(int cost,int weight,int m){
19     for(int i = cost;i <= m;i++){
20         dp[i] = max(dp[i],dp[i-cost]+weight);
21     }
22 }
23 
24 void duochong_pack(int c[],int w[],int num[],int n,int m){
25     memset(dp,0,sizeof(dp));
26     
27     for(int i = 1;i <= n;i++){
28         if(num[i]*c[i] > m) wanquan_pack(c[i],w[i],m);
29         else{
30             int k = 1;
31             while(k < num[i]){
32                 lingyi_pack(k*c[i],k*w[i],m);
33                 num[i] -= k;
34                 k <<= 1; 
35             }
36             lingyi_pack(num[i]*c[i],num[i]*w[i],m);
37         }
38     }
39     
40 //    for(int i = 1;i <= m;i++) printf("dp[%d] = %d\n",i,dp[i]);
41     
42     printf("%d\n",dp[m]);
43 }
44 
45 int main(){
46     int T;
47     scanf("%d",&T);
48     while(T--){
49         memset(c,0,sizeof(c));
50         memset(w,0,sizeof(w));
51         memset(num,0,sizeof(num));
52         scanf("%d %d",&m,&n);
53         for(int i = 1;i <= n;i++) scanf("%d %d %d",&c[i],&w[i],&num[i]);
54         
55         duochong_pack(c,w,num,n,m);
56     }
57     return 0;
58 }
View Code

 

---------9.16

感觉这几天因为协会的事情,都静不下来

老是心里挂着有事情----

不应该这样的-------------------------------------------

没事,,加油加油

加油--

 

hdu 5439

想一早上终于想通了

其实比赛的时候,学弟想对了一点的 ans[i] = sigma i*a[i]

当时我们想的是,n太大了,数组根本开不下来

都有种弃疗的感觉,根本没再仔细往下想了

观察这列数

编号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

数    1 2 2 3 3 4 4 4 5 5 5 6 6 6 7 7 7 7 8 8 8 8

ans[ 1] = 1*1

ans[2] = 1*1 + 2*2

ans[3] = 1*1 + 2*2 + 3*2

ans[4] = 1*1 + 2*2 + 3*2 + 4*3

ans[5] = 1*1 + 2*2 + 3*2 + 4*3+5*3

ans[6] = 1*1 + 2*2 + 3*2 + 4*3 +  5*3 + 6*4

ans[7] = 1*1 + 2*2 + 3*2 + 4*3 +  5*3 + 6*4 + 7*4

ans[8] = 1*1 + 2*2 + 3*2 + 4*3 +  5*3 + 6*4 + 7*4 + 8*4

然后我就卡住了,还在往递推那边想--挫爆-----

然后其实可以合并一下

比如说

ans[6] = 1*1 + 2*(2+3) + 3*(4+5) + 4*(6)

ans[7] = 1*1 + 2*(2+3) + 3*(4+5) + 4*(6+7)

ans[8] = 1*1 + 2*(2+3) + 3*(4+5) + 4*(6+7+8)

观察到它们有公共的前缀,然后把这个公共的前缀处理出来,剩下的那一段算出来再加上去

 

然后前缀的计算办法

首先定义f[i] 为 i 出现的最后的位置,g[i] 表示i连续出现的次数

f[i] = f[i-1] + g[i]

然后就是求g[i]

g[i] = lower_bound(f+1,f+i,i) - f;

这个举两个例子就好想了

然后就是

ans里面括号里面的值的计算

首项 f[i-1] + 1,尾项 f[i],个数 g[i] = (f[i] - f[i-1])

根据等差数列的公式就可以算出来是 (f[i-1] + 1 + f[i]) *(f[i] - f[i-1])/2

看的是这篇题解

http://www.cnblogs.com/CSU3901130321/p/4805973.html

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 
 8 typedef long long LL;
 9 const int maxn = 500000;
10 const int mod = 1e9+7;
11 LL f[maxn+5],g[maxn+5];
12 LL ans[maxn+5];
13 int n;
14 
15 int main(){
16     int T;
17     f[1] = 1;g[1] = 1;
18     f[2] = 3;g[2] = 2;
19     
20     for(int i = 3;i <= maxn;i++){
21         g[i] = lower_bound(f+1,f+i,i)-f;
22         f[i] = f[i-1] + g[i];
23     }
24     ans[1] = 1;
25     
26     for(int i = 2;i <= maxn;i++){
27         ans[i] = ans[i-1] + 1LL*(f[i]+f[i-1]+1)*(f[i]-f[i-1])/2 %mod * 1LL *i %mod;
28     }
29     
30 //    for(int i = 1;i <= 10;i++)
31 //    printf("f[%d] = %I64d  g[%d] = %I64d ans[%d] = %I64d \n",i,f[i],i,g[i],i,ans[i]);
32     
33     scanf("%d",&T);
34     while(T--){
35         scanf("%d",&n);
36         int pos = lower_bound(f+1,f+maxn+1,n)-f;
37     //    printf("pos = %d\n",pos);
38         LL res = ans[pos-1];
39         
40         for(int i = f[pos-1]+1;i <= n;i++){
41             res = (res + 1LL*pos*i)%mod;
42         }
43     
44         printf("%I64d\n",res);
45     }
46     return 0;
47 }
View Code

 

这场网络赛先补到这儿了吧先--

昨晚试图补那题多重背包,想好久一点思路没有

搜题解发现用到两次多重背包,然后通过空间联系起来---

实在不懂---再补吧-----

KMP +最小表示法没学过,,,或者用后缀数组(也没学过)做的那题也先不补吧-------

 

接着滚去 cf 上做题了---

加油↖(^ω^)------

 

cf  216 b

http://codeforces.com/contest/216/problem/B

给出n个人,m个仇恨关系,现在要把这n人平均分成两只队伍,且每只队伍里面不能有相互仇恨的人,问至少得删除多少个人

觉得自己想得情况有点多

先是偶链,偶环不用管

然后是奇点(1个点单独成联通快)的个数 c1

奇链的个数 c2

奇环的个数 c3

每个奇环肯定得删去一个点

然后如果是

偶数个奇点,偶数条奇链,不用管

偶数个奇点,奇数条奇链,删一个点

奇数个奇点,偶数条奇链,删一个点

奇数个奇点,奇数条奇链,不用管

发现做这样的题,得多画几个图,,先一点思路都没有,,还在往二分图那边想---

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 
 8 const int maxn = 105;
 9 vector<int> g[maxn];
10 vector<int> c[maxn];
11 int cnt;
12 int n,m;
13 int vis[maxn];
14 int findd,ok,st;
15 
16 void dfs(int u,int fa){
17     vis[u] = 1;
18     c[cnt].push_back(u);
19     for(int i = 0;i < g[u].size();i++){
20         int v = g[u][i];
21         if(v == fa) continue;
22         if(!vis[v]) dfs(v,u);
23         else{
24             findd = 1;st = v;return;
25         }
26         if(findd){
27             if(ok) return;
28             if(st == u) ok = 1;
29             return;
30         }
31     }
32 }
33 
34 void solve(){
35     memset(vis,0,sizeof(vis));
36     for(int i = 1;i <= n;i++) c[i].clear();
37     
38     cnt = 1;
39     int c1 = 0,c2 = 0,c3 = 0;
40     for(int i = 1;i <= n;i++){
41         if(!vis[i]){
42             findd = 0;ok = 0;
43             dfs(i,0);
44             if(findd && ok && c[cnt].size() %2 == 1) c3++;
45             if(c[cnt].size() == 1) c1++;
46             if(findd == 0 && ok == 0 && c[cnt].size()%2 == 1 && c[cnt].size() != 1) c2++; 
47             cnt++;
48         }
49     }
50     
51     int res = 0;
52     res += c3;
53     if(c1%2 == 1 && c2%2 == 0) res++;
54     if(c1%2 == 0 && c2%2 == 1) res++;
55     printf("%d\n",res);
56 }
57 
58 int main(){
59     while(scanf("%d %d",&n,&m) != EOF){
60         for(int i = 1;i <= n;i++) g[i].clear();
61         
62         for(int i = 1;i <= m;i++){
63             int u,v;
64             scanf("%d %d",&u,&v);
65             g[u].push_back(v);g[v].push_back(u);
66         }
67         solve();
68     }
69     return 0;
70 }
View Code

 

cf 522 b

http://codeforces.com/problemset/problem/522/B

大意是这样的,给出n个矩形的宽 w,高 h

每次去掉当前这个矩形,求剩下的sigma w i * max(h[i])

因为是点的dp标签做的---

所以一直想怎么dp

后来--咦,用线段树查最大值呢---

于是,就每次这样蠢蠢的去查最大值

先将要去掉的那个点置为-1,再查询整个区间的最大值,再把这个值update回来---

可是不对--

每次执行的时候打印了一下线段树那个1---发现根本不是我预期的效果嘛---有些段的最大值还会是上一次的最大值--

后来就分两段查询,i的前面和后面

too  young啊----

后来搜别人的题解---根本没有用线段树,维护一个最大值和次大值----55555555555555555

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 
 8 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
 9 
10 const int maxn = 200005;
11 int w[maxn],h[maxn],res[maxn];
12 int n;
13 int nmax;
14 
15 struct node{
16     int l,r,maxx;
17 }t[4*maxn];
18 
19 void Push_up(int p){
20     t[p].maxx = max(t[p<<1].maxx,t[p<<1|1].maxx);
21 }
22 
23 void Build_tree(int p,int l,int r){
24     t[p].l = l;
25     t[p].r = r;
26     if(l == r){
27         t[p].maxx = h[l];
28         return;
29     }
30     int mid = getmid(l,r);
31     Build_tree(p<<1,l,mid);
32     Build_tree(p<<1|1,mid+1,r);
33     Push_up(p);
34 }
35 
36 void update(int idx,int p,int w){
37     if(t[p].l == t[p].r){
38         t[p].maxx = w;
39         return;
40     }
41     int mid = getmid(t[p].l,t[p].r);
42     if(idx <= mid) update(idx,p<<1,w);
43     else update(idx,p<<1|1,w);
44     Push_up(p);    
45 }
46 
47 void Query(int p,int l,int r){
48     if(t[p].maxx <= nmax) return;
49     if(t[p].l == l && t[p].r == r){
50         nmax = max(nmax,t[p].maxx);
51         return;
52     }
53     int mid = getmid(t[p].l,t[p].r);
54     if(r <= mid) Query(p<<1,l,r);
55     else if(l > mid) Query(p<<1|1,l,r);
56     else{
57         Query(p<<1,l,mid);
58         Query(p<<1|1,mid+1,r);
59     }
60 }
61 
62 int main(){
63     while(scanf("%d",&n) != EOF){
64         memset(w,0,sizeof(w));
65         memset(h,0,sizeof(h));
66         memset(res,0,sizeof(res));
67         int sum = 0;
68         for(int i = 1;i <= n;i++) scanf("%d %d",&w[i],&h[i]),sum += w[i];
69         Build_tree(1,1,n);
70         
71     //    for(int i = 1;i <= 2*n;i++)
72     //    printf("t[%d].l = %d  t[%d].r = %d  t[%d].maxx = %d\n",i,t[i].l,i,t[i].r,i,t[i].maxx);
73         
74         for(int i = 1;i <= n;i++){
75             nmax = -1;
76              if(i-1 > 0) Query(1,1,i-1);
77              int a = nmax;//printf("i = %d  a= %d\n",i,a);
78              if(i+1 <= n) Query(1,i+1,n);
79              int b = nmax;//printf("i = %d  b = %d\n",i,b);
80              nmax = max(a,b);
81         //    printf("i = %d  nmaxx = %d\n",i,nmax);
82             res[i] = (sum-w[i])*nmax;
83         }
84         
85         for(int i = 1;i <= n;i++) printf("%d ",res[i]);
86         printf("\n");
87     }
88     return 0;
89 }
View Code

 

---------9.17

昨晚的cf

cf 575 c

http://codeforces.com/problemset/problem/579/C

C题被卡掉了

今早把输出改成  .9lf就过了-----哭开------

可是我记得以前做这样的题的时候,输出%lf都可以的啊-------

仔细仔细----加油

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 int a,b;
 8 
 9 void solve(){
10     if(a == b){
11         printf("%lf\n",1.0*a);
12         return;
13     }
14     double x1 = 0,x2 = 0;
15     double c1 = (1<<30)-1,c2 =(1<<30)-1;
16     x1 = a-b;
17     x2 = a+b;
18     int y1 = 0,y2 = 0;
19     y1 = a/b-1;
20     if(y1 % 2 == 1) y1--;
21     y2 = a/b + 1;
22     if(y2%2 == 1) y2--;
23     
24     //printf("y1 = %d  y2 = %d\n",y1,y2);
25     
26     if(y1 > 0) c1 = x1/y1;
27     if(y2 > 0) c2 = x2/y2;
28     
29     double res = 0;
30     res = min(c1,c2);
31     if(res == ((1<<30)-1)) puts("-1");
32     else printf("%.9lf\n",res);
33 }
34 
35 int main(){
36     while(scanf("%d %d",&a,&b) != EOF){
37         solve();
38     }
39     return 0;
40 }
View Code

 

cf 579 d

http://codeforces.com/problemset/problem/579/D

给出 n,k,d

再给出n个数,允许k次操作,每次操作可以将其中一个数乘以一个x

问这列数的异或的最大值

 

第一反应是dp---

在想怎么转移---不会啊--

后来又想,贪吧,能够让二进制的位数最长不就可以了么,于是把最大值扫出来,k次操作全部用在最大值上面---wawawa---

今天看题解--

枚举一下把这k次操作放在哪个数上,维护一个最大值就可以了

还有---我太挫了--不会算,每次枚举的时候,除开那个数另外的数的异或起来的值

还在想如果再去for算一遍,绝对T掉啊------

后来CF上翻了份代码-----处理下前缀的异或和后缀的异或就可以了

 

可是为什么要这样做呢------

搞懂了再来补上吧--

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 typedef long long LL;
 8 const int maxn = 200005;
 9 LL a[maxn];
10 int n,k,x;
11 LL pre[maxn],suf[maxn];
12 
13 void solve(){
14     memset(suf,0,sizeof(suf));
15     memset(pre,0,sizeof(pre));
16     
17     for(int i = 1;i <= n;i++) pre[i] = pre[i-1]|a[i];
18     for(int i = n;i >= 1;i--) suf[i] = suf[i+1]|a[i];
19     
20 //    for(int i = 1;i <= n;i++){
21 //        printf("pre[%d] = %I64d  suf[%d] = %II64d\n",i,pre[i],i,suf[i]);
22 //    }
23     
24     LL res = -1;
25     for(int i = 1;i <= n;i++){
26         for(int j = 1;j <= k;j++) a[i] = a[i]*x;
27         LL tmp = pre[i-1]|suf[i+1]|a[i];
28         res = max(res,tmp);
29     }
30     printf("%I64d\n",res);
31 }
32 
33 int main(){
34     while(scanf("%d %d %d",&n,&k,&x) != EOF){
35         for(int i = 1;i <= n;i++) scanf("%I64d",&a[i]);
36         solve();
37     }
38     return 0;
39 }
View Code

----9.18

出题解了,不知道是不是这样理解

假设把那k次分给不止一个数来乘

设这会儿得到的序列为b[]

那么在这乘了x的数中,肯定会有一个最大值,而且这还是在乘的次数不够k次的时候,它就最大了,要更大的话,就把所有的k次都乘给它

但是不知道都乘在哪个数上会最大,所以就去枚举一下

 

 

cf 577 E

http://codeforces.com/problemset/problem/577/E

给出 n个点的坐标,输出一种这n个点的排列方式,使得它们的曼哈顿距离之和小于等于25*10^8

 

尝试了各种排序之后无果--滚去看了题解--

有题解说是构造,有题解说是分块,意思都差不多的感觉

将x按照1000来分块

这样,在每一块里面,对y排序,

比如说第一块,从y由大到小

第二块,从y由小到大

这样顺次连接

可以估算出,每一块的y加起来是小于10^6,总共的x加起来小于 n*10^3(画了个图)

所以是满足的,,,

 

话说,做这题有个小插曲---

 

下午-

自动控制课---

拿着爪机坐在最后一排正瞅着这道题---

突然--

我们和蔼可亲的自动控制老师顿地一下---

“后面那个----------------------------”

我以为他要说,后面那个玩手机的同学,,,,,,,,

吓得飞起---

然后他说

“放大器应该这样来分析----------”

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 
 8 const int maxn = 1000005;
 9 vector<pair<int,int> > res[maxn];
10 
11 int main(){
12     int n;
13     while(scanf("%d",&n) != EOF){
14         for(int i = 0;i < n;i++){
15             int x,y;
16             scanf("%d %d",&x,&y);
17             res[x/1000].push_back(make_pair(y,i));
18         }
19         for(int i = 0;i <= 1000;i++){
20             if(res[i].size() == 0) continue;
21             sort(res[i].begin(),res[i].end());
22             if(i%2 == 0) reverse(res[i].begin(),res[i].end());
23             
24             for(int j = 0;j < res[i].size();j++) printf("%d ",res[i][j].second+1);
25         }
26     }
27     return 0;
28 }
View Code

 

 

---------9.18

cf 150 b

http://codeforces.com/contest/150/problem/B

给出 n,m,k

要求意思是,长度为n的字符串,现在有m个不同的字母,要求长度为n的字符串的长度为k的子串全是回文串

问符合这样条件的字符串有多少个

 

想两天没有想出来,还是看题解了

首先考虑到回文串的特点,就把必须相同的位置合并在一起,

然后最后统计一下有多少个连通块c

连通块与连通块之间是可以任意填不同的字母的

所以答案是 m ^c

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 
 8 typedef long long LL;
 9 const int maxn = 2005;
10 const int mod = 1e9+7;
11 int p[maxn];
12 int n,m,k;
13 
14 int find(int x){ return x == p[x] ? x : p[x] = find(p[x]);}
15 
16 LL quick_mod(LL a, LL b,LL p){  
17     LL ans = 1;  
18     a %= p;  
19     while(b){  
20         if(b & 1){  
21             ans = ans * a % p;  
22             b--;  
23         }  
24         b >>= 1;  
25         a = a * a % p;  
26     }  
27     return ans;  
28 }  
29 
30 void solve(){
31     for(int i = 1;i <= n-k+1;i++){
32         for(int j = i;j <= i+k-1;j++){
33             int a = j;
34             int b = (i+i+k-1)-j;
35             int x = find(a);
36             int y = find(b);
37             if(x != y) p[x] = y;
38         }
39     }
40     int c = 0;
41     
42 //    for(int i = 1;i <= n;i++) printf("find(%d) = %d\n",i,find(i));
43     
44     for(int i = 1;i <= n;i++) if(find(i) == i) c++;
45 //    printf("c = %d\n",c);
46     
47     LL res = 0;
48     res = quick_mod(m,c,mod);
49     printf("%I64d\n",res);
50 }
51 
52 int main(){
53     while(scanf("%d %d %d",&n,&m,&k) != EOF){
54         for(int i = 1;i <= n;i++) p[i] = i;
55         
56         solve();
57     }
58     return 0;
59 }
View Code

 

--------9.19

上午学了下单调栈

下午沈阳网络赛被打惨----

不知道碰到多少次LCA了,都没有去好好学一下--

不说了

 

--------9.20

学了一下在线的LCA

发现昨天的1003分明就是这一题,,,POJ 3417

http://www.cnblogs.com/scau20110726/archive/2013/05/31/3110666.html

还在想网络流---挫爆了---

hdu  5452

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<vector>
  6 using namespace std;
  7 
  8 const int INF = (1<<30)-1;
  9 const int maxn = 40005;
 10 const int MAX_LOG = 16;
 11 
 12 int n,m;
 13 int first[maxn],ecnt,ecnt1,first1[maxn];
 14 int fa[MAX_LOG][maxn],dep[maxn];
 15 int dp[maxn],vis[maxn];
 16 
 17 struct Edge{
 18     int u,v,next,w;
 19 };
 20 
 21 Edge e[10*maxn],ea[10*maxn];
 22 
 23 void init(){
 24     ecnt  = 0;
 25     memset(first,-1,sizeof(first));
 26 }
 27 
 28 void Add_edge(int u,int v){
 29     e[ecnt].u = u;
 30     e[ecnt].v = v;
 31     e[ecnt].next = first[u];
 32     first[u] = ecnt++;
 33 }
 34 
 35 void Dfs(int p,int pre,int d){
 36     fa[0][p] = pre;
 37     dep[p] = d;
 38     for(int i = first[p];~i;i = e[i].next){
 39         int v = e[i].v;
 40         if(v == pre) continue;
 41         Dfs(v,p,d+1);
 42     }
 43 }
 44 
 45 void Pre(){
 46     Dfs(1,-1,0);
 47     for(int k = 0;k+1 < MAX_LOG;++k){
 48         for(int v = 1;v <= n;v++){
 49             if(fa[k][v] < 0) fa[k+1][v] = -1;
 50             else fa[k+1][v] = fa[k][fa[k][v]];
 51         }
 52     }
 53 }
 54 
 55 int Lca(int u,int v){
 56     if(dep[u] > dep[v]) swap(u,v);
 57     for(int k = MAX_LOG-1;k >= 0;--k){
 58         if(dep[v]-dep[u] & (1<<k))
 59         v = fa[k][v];
 60     }
 61     if(u == v) return u;
 62     for(int k = MAX_LOG-1;k >= 0;--k){
 63         if(fa[k][u] != fa[k][v]){
 64             u = fa[k][u];
 65             v = fa[k][v];
 66         }
 67     }
 68     return fa[0][u];
 69 }
 70 
 71 void dfs(int u){
 72     vis[u] = 1;
 73     for(int i = first[u];~i;i = e[i].next){
 74         int v = e[i].v;
 75         if(vis[v]) continue;
 76         dfs(v);
 77         dp[u] += dp[v];
 78     }
 79 }
 80 
 81 int main(){
 82     int T;
 83     scanf("%d",&T);
 84     int kase = 0;
 85     while(T--){
 86         scanf("%d %d",&n,&m);
 87         init();
 88         memset(dp,0,sizeof(dp));
 89         for(int i = 1;i <= n-1;i++){
 90             int u,v;
 91             scanf("%d %d",&u,&v);
 92             Add_edge(u,v);
 93             Add_edge(v,u);
 94         }
 95         
 96         Pre();
 97         for(int i = 1;i <= m-n+1;i++){
 98             int u,v;
 99             scanf("%d %d",&u,&v);
100             dp[u]++;dp[v]++;
101             int lca = Lca(u,v);
102             //printf("lca (%d,%d) = %d\n",u,v,lca);
103             dp[lca] -= 2;
104         }
105         
106     //    for(int i = 1;i <= n;i++) printf("dp[%d] = %d\n",i,dp[i]);
107         
108         memset(vis,0,sizeof(vis));
109         dfs(1);
110     ///    for(int i = 1;i <= n;i++) printf("dp[%d] = %d\n",i,dp[i]);
111         
112         int res = INF;
113         for(int i = 2;i <= n;i++) res = min(res,dp[i]);
114         printf("Case #%d: %d\n",++kase,res+1);
115     }
116     return 0;
117 }
View Code

 

转载于:https://www.cnblogs.com/wuyuewoniu/p/4806257.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值