2021.10.18

T1:密钥

Problem:

在这个问题中,⼀个密钥是指⼀个长度为 3n 的⼆进制序列,其中 n 是正整数。
序列的每⼀位从左往右依次被编号为 1 到 3n。⽽⼀个密钥的权值是指相邻位不同的位置个数再加上 1。⽐如:000 的权值是 1, 011010100 的权值是 7。
密钥可以被修改, 确切地说,可以不断进⾏下⾯的操作:选择任意两个相邻的位,然后同时取反它们。
⽐如我们可以通过⼀次操作把 000 修改为 110 。给定⼀个长度为 3n 的密钥,请操作不超过 n 次,将其修改为⼀个权值不少于 2n 的密钥。你可以认为合法解必然存在。

Code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1000005;
 4 char s[N];
 5 int n;
 6 const int op[]={1,2,0,1,0,0,0,2,2,0,0,0,1,0,2,1};
 7 int ans[N];
 8 int main(){
 9     scanf("%s",s+1);
10     n=strlen(s+1)/3;
11     for(int i=1;i<=3*n;i++) s[i]-='0';
12     for(int i=0;i<n;i++){
13         int t=(s[3*i]<<3)+(s[3*i+1]<<2)+(s[3*i+2]<<1)+(s[3*i+3]<<0);
14         if(op[t]){
15             ans[++*ans]=3*i+op[t];
16             s[3*i+op[t]]^=1;
17             s[3*i+op[t]+1]^=1;
18         }
19     }
20     printf("%d\n",*ans);
21     for(int i=1;i<=*ans;i++) printf("%d ",ans[i]);
22     return 0;
23 }

T2:统计

Problem:

给定一个数字 m 和 n 次操作,第 i 次操作有 pi 的百分比的概率成功。如果第 i 次成功,那么 m 会加上一个数字 ai (ai 为正整数或者 -1),求 n 次操作以后成功次数不小于 l 且 m >= 0 的概率。

Code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,l,a,d=1,i,j,k;
 4 const int N=210;
 5 double p[N],f[2][N][N<<1],ans;
 6 int main(){
 7     scanf("%d%d%d",&n,&l,&m);
 8     m=min(n,m);
 9     for(i=1;i<=n;++i){
10         scanf("%lf",&p[i]);
11         p[i]/=100;
12     }
13     f[0][0][n+m]=1;
14     for(i=1;i<=n;++i,d^=1){
15         scanf("%d",&a);
16         for(j=0;j<=n;++j){
17             for(k=0;k<=(n<<1);++k){
18                 f[d][j][k]=f[d^1][j][k]*(1-p[i]);
19             }
20         }
21         for(j=0;j<=n-1;++j){
22             for(k=1;k<=(n<<1);++k){
23                 f[d][j+1][min(n<<1,k+a)]+=f[d^1][j][k]*p[i];
24             }
25         }
26     }
27     for(i=l;i<=n;++i){
28         for(j=n;j<=(n<<1);++j){
29             ans+=f[n&1][i][j];
30         }
31     }
32     printf("%.6f",ans);
33     return 0;
34 }

T3:图

Problem:

现在有⼀个双卡⼿机,对于两个运营商的卡可以同时⼯作。你可以发送短信给某个⼿话号码,通过两个运营商中花钱更少的⼀个。
不过并⾮所有⼿机运营商可以通过他们发送短信给其他运营商的⼿话号码。请你选择⼀对运营商,使⼿机能
发送短信给所有运营商的⼿话号码,⽽且发送短信的最⼤费⽤最少 。
注意,在这道题中,⾃⼰已选定的运营商不默认能给⾃⼰发短信。选定的两个运营商也要求能够被发到短信。
如果你还是没看懂可以看看样例。

Code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=10000+5;
 4 const int M=10*N;
 5 typedef bitset<N> Int;
 6 Int F[N],standerd;
 7 int n,m,tim[N],deg[N],a[M];
 8 struct data{
 9     int x,y,val;
10     bool operator<(const data &z) const{
11         if(x!=z.x) return x<z.x;
12         if(y!=z.y) return y<z.y;
13         return val<z.val;
14     } 
15     bool operator != (const data &z) const{
16         return x!=z.x||y!=z.y;
17     }
18 }edge[M];
19 vector<int>V[N];
20 inline bool check(int mid){
21     static const int base=2050;
22     if(n>base){
23         for(int i=1;i<=n;++i){
24             deg[i]=0;
25             for(int j=0;j<V[i].size();++j){
26                 int temp=V[i][j];
27                 if(edge[temp].val<=mid) deg[i]++;
28             }
29         }
30         for(int i=1;i<=n;++i) tim[i]=-1;
31         for(int i=1;i<=n;++i){
32             if(deg[i]*2>=n){
33                 for(int j=0;j<V[i].size();++j){
34                     int temp=V[i][j];
35                     if(edge[temp].val<=mid) tim[edge[temp].y]=i;
36                 }
37                 for(int j=1;j<=n;++j){
38                     if(deg[i]+deg[j]>=n&&deg[i]>=deg[j]){
39                         int temp=deg[i];
40                         for(int k=0;k<V[j].size();++k){
41                             int temp2=V[j][k];
42                             if(edge[temp2].val<=mid&&tim[edge[temp2].y]<i) temp++;
43                         }
44                         if(temp==n) return true;
45                     }
46                 }
47             }
48         }
49     }
50     else{
51         for(int i=1;i<=n;++i) F[i]=standerd;
52         for(int i=1;i<=n;++i){
53             deg[i]=0;
54             for(int j=0;j<V[i].size();++j){
55                 int temp=V[i][j];
56                 if(edge[temp].val<=mid){
57                     deg[i]++;
58                     F[i].reset(edge[temp].y);
59                 }
60             }
61         }
62         for(int i=1;i<=n;++i){
63             if(deg[i]*2>=n){
64                 for(int j=1;j<=n;++j){
65                     if(deg[j]+deg[i]>=n&&deg[i]>=deg[j]){
66                         Int temp=F[i]&F[j];
67                         if(!temp.any()) return true;
68                     }
69                 }
70             }
71         }
72     }
73     return false;
74 }
75 int main(){
76     scanf("%d%d",&n,&m);
77     for(int i=1;i<=n;++i) standerd.set(i);
78     for(int i=1;i<=m;++i){
79         scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].val);
80     }
81     sort(edge+1,edge+m+1);
82     int top=1;
83     for(int i=2;i<=m;++i) if(edge[i]!=edge[i-1]) edge[++top]=edge[i];
84     m=top;
85     for(int i=1;i<=m;++i) a[i]=edge[i].val;   
86     sort(a+1,a+m+1);
87     for(int i=1;i<=m;++i) V[edge[i].x].push_back(i);
88     int l=1,r=m+1;
89     while(l<r){
90         int mid=(l+r)>>1;
91         if(check(a[mid])) r=mid;
92         else l=mid+1;
93     }
94     if(l==m+1) puts("No solution");
95     else cout<<a[l]<<endl;
96 }

 

posted @ 2021-10-20 17:42  B_lank  阅读(38)  评论(0编辑  收藏  举报