三道题,几乎爆零,状态很不好,考到一半直接写数学作业去了。。
1.
时间限制:1s 空间限制:1M
Description
给出2n个正整数,有且只有两个数出现奇数次,从小到大输出这两个数。
Input
第一行给出一个n,第二行有2n个数。
Output
从小到大输出答案。
Simple Input 1 | Simple Output 1 |
---|---|
5 | 1 6 |
1 2 3 4 5 2 3 4 5 6 |
Simple Input 2 | Simple Output 2 |
---|---|
2 | 1 2 |
1 1 1 2 |
Hint
n<=100000 所有数字均不超过int且均为正整数
看起来就很难的样子。只有两个数出现了奇数次,自然想到xor,所有数xor,最后的xor值就是a^b的值。然后怎么判断a,b究竟是哪两个数?
1010110 对于前面这个数(记为sum),假如是两个数^而成,那么sum某位置是1(记此位置为pos),a,b中必有某一个数这一位为1,另一个数此位为0。
用sum去^所有pos位为1的数,得到的就是a,b其中一个数,另一个数用 sum^已得的数就好了。
还有一点,此题数据范围太大而空间太小(后来数据又加强了),不可能存下所有给出的数。所以必须预处理出某一位为1时所有此位为1的数异或出的值。
CODE:
1 #include<cstdio> 2 using namespace std; 3 int bit[32],sum,n; 4 int main(){ 5 freopen("one.in","r",stdin);freopen("one.out","w",stdout); 6 scanf("%d",&n);n*=2; 7 int x,a,b; 8 for(int i=1;i<=n;i++){ 9 scanf("%d",&x);sum^=x; 10 for(int j=0;j<32;j++) 11 if((x>>j)&1)bit[j]^=x; 12 } 13 for(int i=0;i<32;i++){ 14 if(sum>>i&1){ 15 a=bit[i]; 16 b=sum^bit[i]; 17 } 18 } 19 if(a>b){int t=a;a=b;b=t;} 20 printf("%d %d",a,b); 21 return 0; 22 }
2
时间:1s 空间:256M
Simple Input 1 | Simple Output 1 |
---|---|
5 1 1 0 | 1 |
0 |
Simple Input 2 | Simple Output 2 |
---|---|
10 19260817 7 3 | 2 |
1 3 5 7 9 |
Hint n<=1000000 此题有多种方案,任意输出一种即可
通过样例可以看出,后面的商品价格有点高。。
这么思考:可以购买连续的一段区间来达到目的。
那么只需要记录对n取模后的前缀和,如果某商品(标号记为to)的前缀和等于在它之前某商品(记为to)的前缀和,只需要购买from和to之间的商品就行。
这样购买一定有解。原因:算上0(一个都不买),共有n+1个前缀和,那么一定有2个前缀和相同,所以一定有解。
CODE:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define ll long long 7 #define inf 2147483647 8 #define N 10000005 9 using namespace std; 10 int sum[N],vis[N],A,B,n,from,to; 11 ll lt; 12 int main(){ 13 freopen("rich.in","r",stdin);freopen("rich.out","w",stdout); 14 scanf("%d%d%d%I64d",&n,&A,&B,<); 15 if(lt==0){printf("1\n0");return 0;} 16 for(int i=0;i<=n;i++)vis[i]=-1; 17 sum[1]=lt%n;sum[0]=0; 18 vis[sum[1]]=1;vis[0]=0; 19 for(int i=2;i<=n;i++){ 20 lt=(1ll*A*lt+B)%n; 21 sum[i]=(sum[i-1]+lt)%n; 22 if(vis[sum[i]]>=0){ 23 from=vis[sum[i]]+1; 24 to=i;break; 25 } 26 else vis[sum[i]]=i; 27 } 28 printf("%d\n",to-from+1); 29 for(int i=from-1;i<=to-1;i++)printf("%d ",i); 30 return 0; 31 }
3
时间:1s 空间:256M
Description
给出一个的地图,然而只有一些地方有Wi-Fi,dp66为了看直播,只走有Wi-Fi的地方。
现在Ta想从左上角到右下角,问最少要移动多少Wi-Fi覆盖区域,使得Ta可以到终点。
Input
第一行有两个数,接下来是一个的地图,‘.‘表示空地,‘#‘表示有Wi-Fi覆盖。
Output
输出最少移动区域数,若无法这输出-1。
Simple Input 1
4 7 #...### #...#.# ##..#.# .#....#
Simple Output 1
3
Simple Input 2
4 5 ..... .###. ####. .....
Simple Output 2
-1
Hint n<=m<=50 就是一个bfs,移动的wifi的个数=路径上走过的‘ . ‘的个数。 用最短路的思想优化,否则TLE。 优化:如果此前通过某种途径到达此点的所走过的‘ . ‘的个数比这条路径所走的‘ . ‘的个数少,那么此条路径不再向后拓展。道理很显然。CODE:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 #define ll long long 8 #define inf 2147483647 9 #define N 2505 10 using namespace std; 11 int n,m,cnt,dp[55][55][N]; 12 int dx[]= {0,0,1,-1}; 13 int dy[]= {1,-1,0,0}; 14 15 char mp[55][55]; 16 struct node { 17 int x,y,pit,wif; 18 bool operator <(const node &a)const { 19 return pit>a.pit; 20 } 21 }; 22 priority_queue<node>q; 23 24 25 void solve() 26 { 27 node st; 28 st.x=st.y=1; 29 st.pit=(mp[1][1]==‘.‘); 30 st.wif=(mp[1][1]==‘#‘); 31 q.push(st); 32 while(!q.empty()) { 33 node u=q.top(); 34 q.pop(); 35 int x=u.x,y=u.y,wif=u.wif,pit=u.pit; 36 if(x==n&&y==m) { 37 printf("%d",pit); 38 break; 39 } 40 node v; 41 for(int i=0; i<4; i++) { 42 v.x=x+dx[i]; 43 v.y=y+dy[i]; 44 if(v.x>n||v.x<1||v.y>m||v.y<1)continue; 45 v.wif=u.wif+(mp[v.x][v.y]==‘#‘); 46 v.pit=pit+(mp[v.x][v.y]==‘.‘); 47 if(v.pit>=dp[v.x][v.y][v.pit])continue;//剪枝 48 dp[v.x][v.y][v.pit]=v.pit; 49 q.push(v); 50 } 51 } 52 } 53 54 int main() 55 { 56 freopen("way.in","r",stdin); 57 freopen("way.out","w",stdout); 58 scanf("%d%d",&n,&m); 59 memset(dp,0x3f,sizeof(dp)); 60 for(int i=1; i<=n; i++) { 61 scanf("%s",mp[i]+1); 62 for(int j=1; j<=m; j++) 63 if(mp[i][j]==‘#‘)cnt++; 64 } 65 if(cnt<n+m-1)printf("-1"); 66 else solve(); 67 return 0; 68 }