【中途相遇法】【STL】BAPC2014 K Key to Knowledge (Codeforces GYM 100526)
2016-08-25 20:36
423 查看
题目链接:
http://codeforces.com/gym/100526
http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11674&courseid=0
题目大意:
N个学生M道题(1<=N<=12,1<=M<=30),每道题只有正误两种选项(0 1),每个学生的答题情况和正确题数已知,求标准答案可能有多少种。
如果标准答案只有一种则输出标准答案,否则输出解的个数。
题目思路:
【中途相遇法】【STL】
如果枚举每道题的正误时间复杂度是O(N*2M),肯定T了。所以考虑中途相遇法。
首先枚举前M/2道题的标准答案的正误,统计出每个状态每个学生的正确题数。
(答案的状态用二进制压缩,学生的正确题数用31进制压缩)先把每个学生答对题数的状态存进ss里
之后用一个map存下当前学生正确题数状态有几种符合条件的,并且存下任意一种答案的状态。
接下来枚举剩下的M-M/2道题目,统计学生正确题数的状态x,判断ss-x是否出现过(即前M/2道题有没有能够与现在匹配的状态),出现过则ans加上出现次数。
最后根据ans数量输出即可。
http://codeforces.com/gym/100526
http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11674&courseid=0
题目大意:
N个学生M道题(1<=N<=12,1<=M<=30),每道题只有正误两种选项(0 1),每个学生的答题情况和正确题数已知,求标准答案可能有多少种。
如果标准答案只有一种则输出标准答案,否则输出解的个数。
题目思路:
【中途相遇法】【STL】
如果枚举每道题的正误时间复杂度是O(N*2M),肯定T了。所以考虑中途相遇法。
首先枚举前M/2道题的标准答案的正误,统计出每个状态每个学生的正确题数。
(答案的状态用二进制压缩,学生的正确题数用31进制压缩)先把每个学生答对题数的状态存进ss里
之后用一个map存下当前学生正确题数状态有几种符合条件的,并且存下任意一种答案的状态。
接下来枚举剩下的M-M/2道题目,统计学生正确题数的状态x,判断ss-x是否出现过(即前M/2道题有没有能够与现在匹配的状态),出现过则ans加上出现次数。
最后根据ans数量输出即可。
// //by coolxxx //#include<bits/stdc++.h> #include<iostream> #include<algorithm> #include<string> #include<iomanip> #include<map> #include<memory.h> #include<time.h> #include<stdio.h> #include<stdlib.h> #include<string.h> //#include<stdbool.h> #include<math.h> #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #define abs(a) ((a)>0?(a):(-(a))) #define lowbit(a) (a&(-a)) #define sqr(a) ((a)*(a)) #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) #define mem(a,b) memset(a,b,sizeof(a)) #define eps (1e-8) #define J 10 #define mod 1000000007 #define MAX 0x7f7f7f7f #define PI 3.14159265358979323 #define N 14 #define M 34 using namespace std; typedef long long LL; int cas,cass; int n,m,lll,ans; char s [M]; int a ,l ,r ; int f[65544]; int z; LL ss; map<LL,int>num,t; void init() { int i,j; for(i=1;i<=(1<<16);i++) for(j=i;j;j>>=1) f[i]+=(j&1); } int main() { #ifndef ONLINE_JUDGE // freopen("1.txt","r",stdin); // freopen("2.txt","w",stdout); #endif int i,j,k; LL x; init();//统计每个数字2进制下有几个1 for(scanf("%d",&cass);cass;cass--) // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) // while(~scanf("%s",s+1)) // while(~scanf("%d",&n)) { scanf("%d%d",&n,&m); ans=0;mem(l,0);mem(r,0);num.clear();t.clear(); for(i=1;i<=n;i++) scanf("%s%d",s[i],&a[i]); for(i=1,ss=0;i<=n;i++) ss=ss*31+a[i]; cas=m/2; for(i=1;i<=n;i++) { for(j=0;j<cas;j++) l[i]=l[i]*2+s[i][j]-'0';//前m/2道题 for(j=cas;j<m;j++) r[i]=r[i]*2+s[i][j]-'0';//后m-m/2道题 } for(j=0;j<(1<<cas);j++) { for(i=1,x=0;i<=n;i++) { x=x*31+cas-f[l[i]^j];//31进制,前m/2道题状态为j的n个人的答对题数,f[l[i]^j]为错误题数 if(cas-f[l[i]^j]>a[i])break; } if(i<=n)continue; num[x]++;t[x]=j<<(m-cas);//学生的状态数num和这个状态下题目答案的状态t } cas=m-cas; for(j=0;j<(1<<cas);j++) { for(i=1,x=0;i<=n;i++) { x=x*31+cas-f[r[i]^j];//f[r[i]^j]为错误题数 if(cas-f[r[i]^j]>a[i])break; } if(i<=n)continue; if(num[ss-x])//与前面的状态匹配 { ans+=num[ss-x]; z=t[ss-x]+j; } } if(ans==1) { for(i=(1<<(m-1));i;i>>=1) printf("%d",((i&z)==i)); puts(""); } else printf("%d solutions\n",ans); } return 0; } /* // // */
相关文章推荐
- 树莓派3与MTH01温湿度传感器 、yeelink(python代码实现)
- Android-实现对指定电话的短信拦截和来电拦截
- HDU 5769 Substring(后缀数组)
- RasGetEapUserData
- APP原型设计利器-墨刀MockingBot
- BLE-NRF51822教程-RSSI获取
- Ubuntu16.04,windows盘符无法访问
- 使用EPEL YUM源安装R
- 二叉树中找两个结点的最近公共祖先结点
- 1028 人口普查
- nrf51822-主从通信分析2
- [150925]見合い結婚した幼妻が男の娘だった件【日文硬盘版】[带全CG存档+日本语启动&自动打开存档补丁]
- 互联网-手机圈那些事
- 一些需要准备的东西
- 实现了一个延时几秒钟的开始activity的图像画面,然后转换到其他Activity
- PHP 运行流程
- React 动态增加compoent
- nrf51822-主从通信分析1
- 测试
- <Android 应用 之路> 百度地图API使用(1)