【5.5考試】
三道題,幾乎爆零,狀態很不好,考到一半直接寫數學作業去了。。
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 forView Code(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 }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考試】