2019 Wannafly summer camp Day2

Day2 还是很有难度的emmmm

A - Por Costel and Azerah

给定n个数,从其中取出若干个数使其和为偶数,问有多少种取法

(1)dp做法:挖坑待更

(2)数学做法:可以分为三种情况:

        1,从奇数中取2*x个 s1=C(n,2)+C(n,4)+...+C(n,n/2*2)

        2,从偶数中取任意个s2=C(n,1)+C(n,2)+C(n,3)+...+C(n,n)

        3,从奇数中取2*x个,偶数中取任意个s3=s1*s2

        用组合数可以算出来

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int odd,even;
 4 const int mod=1e9+7;
 5 int power(int a,int n)
 6 {
 7     int ans=1,tmp=a;
 8     while(n)
 9     {
10         //cout<<ans<<endl;
11         if(n&1) ans=1ll*ans*tmp%mod;
12         tmp=1ll*tmp*tmp%mod;
13         n/=2;
14     }
15     return ans;
16 }
17 int main()
18 {
19     freopen("azerah.in","r",stdin);
20     freopen("azerah.out","w",stdout);
21     ios::sync_with_stdio(0);
22     int n,t;cin>>t;
23     while(t--){
24         even=odd=0;
25     cin>>n;
26     for(int i=1;i<=n;++i)
27     {
28         int t;cin>>t;
29         if(t&1) ++odd;
30         else ++even;
31     }
32     int s1=power(2,odd-1)-1,s2=power(2,even)-1;
33     if(odd==0) s1=0;if(even==0) s2=0;
34     long long ans=(s1+s2+1ll*s1*s2)%mod;
35     cout<<ans<<endl;
36     }
37 }
View Code

 

 

 

B - Por Costel and the Algorithm

参考https://www.cnblogs.com/autsky-jadek/p/6338115.html

给一个有向图,求它的最短路树,先输出最短路树的边,再输出其他边

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define pil pair<int,ll>
 4 #define mem(a) memset(a,0,sizeof(a))
 5 using namespace std;
 6 const int maxn=2e5+5;
 7 ll dis[maxn];
 8 int fir[maxn],pre[maxn],n,m,cnt;
 9 bool vis[maxn],used[maxn*2];
10 struct edge { int to,v,nex;}E[maxn*2];
11 struct cmp { bool operator()(pil a,pil b){return a.second>b.second;}};
12 void add(int fro,int to,int v){E[++cnt].to=to,E[cnt].v=v,E[cnt].nex=fir[fro],fir[fro]=cnt;}
13 void ini(){mem(fir),mem(pre),mem(vis),mem(E),mem(used);fill(dis,dis+maxn,1e18);cnt=0;}
14 void dfs(int now)
15 {
16     for(int i=fir[now];i;i=E[i].nex)
17     {
18         if(used[i])
19         {
20             cout<<i<<" ";
21             dfs(E[i].to);
22         }
23     }
24 }
25 void dij()
26 {
27     priority_queue<pil,vector<pil>,cmp>pq;
28     pq.push({1,0});
29     dis[1]=0;
30     while(!pq.empty())
31     {
32         int now=pq.top().first;
33         pq.pop();
34         if(vis[now]) continue;
35         vis[now]=1;
36         for(int i=fir[now];i;i=E[i].nex)
37         {
38             int to=E[i].to,
39                 v=E[i].v;
40             if(vis[to]==0 && dis[to]>dis[now]+v)
41             {
42                 //cout<<"test:"<<endl;
43                 //printf("i: %d now: %d to:%d used: %d pre: %d\n",i,now,to,used[pre[to]],pre[to]);
44                 dis[to]=dis[now]+v;
45                 used[pre[to]]=0;
46                 used[i]=1;
47                 pre[to]=i;
48                 pq.push({to,dis[to]});
49             }
50         }
51     }
52 }
53 int main()
54 {
55     freopen("algoritm.in","r",stdin);
56     freopen("algoritm.out","w",stdout);
57     ios::sync_with_stdio(0);
58     int t;cin>>t;
59     while(t--)
60     {
61         ini();
62         cin>>n>>m;
63         for(int i=1;i<=m;++i)
64         {
65             int a,b,c; cin>>a>>b>>c;
66             add(a,b,c);
67         }
68         dij();
69         dfs(1);
70         for(int i=1;i<=m;++i) if(!used[i]) cout<<i<<" "; 
71         cout<<endl;
72     }
73 }
前向星版本
 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 #define mem(a) memset(a,0,sizeof(a))
 4 using namespace std;
 5 const int maxn=1e5+5;
 6 struct pii{int to,v,id;};
 7 struct pil{int first;ll second;};
 8 struct cmp{bool operator()(pil a,pil b){return a.second>b.second;}};
 9 vector<pii>G[maxn];
10 int pre[maxn],n,m;
11 ll dis[maxn];
12 bool vis[maxn],used[maxn*2];
13 void ini() { mem(pre),mem(vis),mem(used);for(int i=0;i<maxn;++i)G[i].clear();fill(dis,dis+maxn,1e18);}
14 void dij()
15 {
16     priority_queue<pil,vector<pil>,cmp>pq;
17     pq.push({1,0});
18     dis[1]=0;
19     while(!pq.empty())
20     {
21         int now=pq.top().first;
22         pq.pop();
23         if(vis[now]) continue;vis[now]=1;
24         for(auto t:G[now])
25         {
26             int to=t.to,v=t.v,id=t.id;
27             if(!vis[to] && dis[to]>dis[now]+v)
28             {
29                 dis[to]=dis[now]+v;
30                 pq.push({to,dis[to]});
31                 used[pre[to]]=0;
32                 pre[to]=id;
33                 used[id]=1;
34             }
35         }
36     }
37 }
38 void dfs(int now)
39 {
40     for(auto t:G[now])
41     {
42         int to=t.to;
43         if(used[t.id])
44         {
45             cout<<t.id<<" ";
46             dfs(to);
47         }
48     }
49 }
50 int main()
51 {
52     freopen("algoritm.in","r",stdin);
53     freopen("algoritm.out","w",stdout);
54     ios::sync_with_stdio(0);
55     int t;cin>>t;
56     while(t--) {
57         ini();
58         cin >> n >> m;
59         for (int i = 1; i <= m; ++i) {
60             int a, b, c;
61             cin >> a >> b >> c;
62             G[a].push_back({b, c, i});
63         }
64         dij();
65         dfs(1);
66         for(int i=1;i<=m;++i) if(used[i]==0) cout<<i<<" ";cout<<endl;
67     }
68 }
vector版本

F - Por Costel and the Alien Invasion

 题意:每个线段有一个权值(高度),有以下操作:

  (1)加入一条线段

  (2)删除最近加入的一条线段

  (3)给一个坐标(线段上的点),查询这个点对应的最低线段的权值

  RMQ,对于每个区间维护一个vector,对于后来的线段,如果位置比原本的低,更新,否则再加上一个当前的区间高度即可。删除直接pop_back。

  

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=3e5+5;
 4 const int inf=1e9+9;
 5 vector<int>tree[maxn<<2];
 6 #define pii pair<int,int>
 7 void insert(int nl,int nr,int root,int l,int r,int v)
 8 {
 9     //cout<<"QAQ";
10     if (l >= nl && r <= nr) {
11         int back = tree[root].empty()?inf:tree[root].back();
12         tree[root].push_back(v < back ? v : back);
13         return;
14     }
15     int mid=(l+r)/2;
16     if (nl <= mid) insert(nl, nr, root*2, l, mid, v);
17     if (nr > mid) insert(nl, nr, root*2+1, mid + 1, r, v);
18 }
19 void del(int nl,int nr,int root,int l,int r)
20 {
21     if(nl<=l && r<=nr)
22     {
23         tree[root].pop_back();
24         return;
25     }
26     int mid=(l+r)/2;
27     if(nl<=mid) del(nl,nr,root*2,l,mid);
28     if(nr>mid) del(nl,nr,root*2+1,mid+1,r);
29 }
30 int query(int pos,int root,int l,int r)
31 {
32     if(l==r)
33     {
34         if(tree[root].size()==0) return inf;
35         else return tree[root].back();
36     }
37     int mid=(l+r)/2;
38     int ans;
39     if(tree[root].size()==0) ans=inf;
40     else ans=tree[root].back();
41     if(pos<=mid) return min(ans,query(pos,root*2,l,mid));
42     else return min(ans,query(pos,root*2+1,mid+1,r));
43 }
44 int main()
45 {
46     freopen("invazia.in","r",stdin);
47     freopen("invazia.out","w",stdout);
48     int n,m;vector<pii>pla;
49     scanf("%d%d",&n,&m);
50     for(int i=1;i<=m;++i)
51     {
52         char t;scanf(" %c",&t);
53         if(t=='I')
54         {
55             int a,b,c;scanf("%d%d%d",&a,&b,&c);
56             pla.push_back({a,b});
57             insert(a,b,1,1,n,c);
58         }
59         else if(t=='E'){
60             del(pla.back().first,pla.back().second,1,1,n);
61             pla.pop_back();
62         } else {
63             int pos;scanf("%d",&pos);
64             int ans=query(pos,1,1,n);
65             if(ans==inf) puts("GUITZZZ!");
66             else printf("%d\n",ans);
67         }
68     }
69 }
View Code

 

H - Por Costel and the Match

分类并查集,参考poj食物链

还有一个做法是带权并查集不过先占个坑

 

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5+5;
 4 int fa[maxn];
 5 int fin(int x){return x==fa[x]?x:fa[x]=fin(fa[x]);}
 6 
 7 int main()
 8 {
 9     freopen("meciul.in","r",stdin);
10     freopen("meciul.out","w",stdout);
11     int t;scanf("%d",&t);
12 while(t--)
13 {
14     int n,m;
15     scanf("%d%d",&n,&m);
16     for(int i=1;i<maxn;++i) fa[i]=i;
17     for(int i=1;i<=m;++i)
18     {
19         int a,b;
20         scanf("%d%d",&a,&b);
21         int x=fin(a),y=fin(b),c=fin(a+n);
22         if(x==y) puts("NO");
23         else{
24             puts("YES");
25             a=fin(a+n),b=fin(b+n);
26             fa[y]=a;
27             fa[x]=b;
28         }
29     }
30 }
31 }
View Code

 

I - Por Costel and the Pairs

数形结合一下?画个y=k/x的图像,用面积搞一下

(牛逼网友说可以分块打表emmm)

 

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 
 5 signed main()
 6 {
 7     freopen("perechi3.in","r",stdin);
 8     freopen("perechi3.out","w",stdout);
 9     ios::sync_with_stdio(0);
10     int t;cin>>t;
11     while (t--)
12     {
13         int n;cin>>n;
14         int i;
15         int ans=0;
16         for(i=1;i*i<=n;++i)
17         {
18             ans+=n/i;
19         }
20         ans=ans*2-(--i)*i;
21         cout<<ans<<endl;
22     }
23 }
View Code

 

K - Por Costel and the Firecracker

根据mod,可知要求的数下标在1e7级别,不过限制了内存,所以可以分块打表,先隔1000个打表一次,可以得到一个1e4的表,对于每次询问,可以在1000次之内得到结果

(也可以隔100个打表一次,合理即可)注意下标要从0开始

这是隔100的

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+5;
 4 const int mod=1e7+3;
 5 int pos[maxn];
 6 int main()
 7 {
 8     freopen("pocnitoare.in","r",stdin);
 9     freopen("pocnitoare.out","w",stdout);
10     ios::sync_with_stdio(0);
11     int n,a,b,x,q,q1;
12 
13     int ans=0;
14     cin>>n>>a>>b>>x>>q>>q1;
15     int xx=x;
16     pos[0]=x-a;
17     for(int i=1;i<=10000000;++i)
18     {
19         if(i%100==0)
20         {
21             pos[i/100]=x;
22         }
23         if(i==q1) ans=x;
24         x=(1ll*i*x+a)%n;
25     }
26     cout<<ans<<endl;
27     int tmp=ans;
28     for(int i=2;i<=q;++i)
29     {
30         int qnow=((1ll*tmp*(i-1)+b)+1)%mod;
31         int start=qnow/100;
32         tmp=pos[start];
33         for(int j=start*100;j<qnow;++j)
34         {
35             tmp=(1ll*j*tmp+a)%n;
36             if(j==0) tmp=xx;
37         }
38         cout<<tmp<<endl;
39     }
40 }
View Code

L - Por Costel and the Semipalindromes

定义半回文串是一定长度的前缀和后缀相等的字符串,给定n和k,求一个长度为n的字典序第k小的半回文串

前缀/后缀长度取1即可

把k分解为长度为n-1的01串即可,并使s[n]=s[1]

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 int n,k;
 5 vector<int> div(int nn)
 6 {
 7     vector<int>v;
 8     while(nn)
 9     {
10         v.push_back(nn&1);
11         nn/=2;
12     }
13     while (v.size()<n-1)
14     {
15         v.push_back(0);
16     }
17     reverse(v.begin(),v.end());
18     return v;
19 }
20 signed main()
21 {
22     freopen("semipal.in","r",stdin);
23     freopen("semipal.out","w",stdout);
24     ios::sync_with_stdio(0);
25     int t;cin>>t;
26     while(t--)
27     {   
28         cin>>n>>k;
29         vector<int>v;
30         v=div(k-1);
31         v.push_back(v[0]);
32         for(int i:v)cout<<(i?'b':'a');
33         cout<<endl;
34     }
35 }
View Code

 

睡了,待更。。。(咕了,以后没了)

UPD:8.16,补F。

 

转载于:https://www.cnblogs.com/codeoosacm/p/11300002.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值