1. 程式人生 > >【5.5考試】

【5.5考試】

tab png scanf ret review stdin while lap bre

  三道題,幾乎爆零,狀態很不好,考到一半直接寫數學作業去了。。

1.

時間限制:1s 空間限制:1M

Description

給出2n個正整數,有且只有兩個數出現奇數次,從小到大輸出這兩個數。

Input

第一行給出一個n,第二行有2n個數。

Output

從小到大輸出答案。

Simple Input 1Simple Output 1
5 1 6
1 2 3 4 5 2 3 4 5 6

Simple Input 2Simple 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 }
View Code

  2

時間:1s 空間:256M

技術分享

Simple Input 1Simple Output 1
5 1 1 0 1
0
Simple Input 2Simple 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,&lt);
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 }
View Code

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 }
View Code


【5.5考試】