2017-10-1 清北刷題沖刺班a.m
位運算1
(bit)
Time Limit:1000ms Memory Limit:128MB
題目描述
LYK擁有一個十進制的數N。它賦予了N一個新的意義:將N每一位都拆開來後再加起來就是N所擁有的價值。例如數字123擁有6的價值,數字999擁有27的價值。
假設數字N的價值是K,LYK想找到一個價值是K-1的數字,當然這個答案實在太多了,LYK想使得這個價值為K-1的數字盡可能大。
輸入格式(bit.in)
一個數N。
輸出格式(bit.out)
一個數表示答案。你需要輸出一個非負整數,且這個數不包含前導0。
輸入樣例1
199
輸出樣例1
198
輸入樣例2
1000
輸出樣例2
0
對於20%的數據n<=10
對於40%的數據n<=100
對於60%的數據n<=1000
對於100%的數據1<=n<=100000。
#include<iostream> #include<cstdio> using namespace std; #define maxn 10 int n,bit[maxn],len; int main(){ freopen("bit.in","r",stdin);freopen("bit.out","w",stdout); scanf(100分"%d",&n); while(n){ bit[++len]=n%10; n/=10; } int now=1; while(bit[now]==0)now++; bit[now]--; while(bit[len]==0&&len>=1)len--; if(len==0)printf("0"); else for(int j=len;j>=1;j--)printf("%d",bit[j]); fclose(stdin);fclose(stdout);return 0; }
火柴棒
(stick)
Time Limit:1000ms Memory Limit:128MB
題目描述
眾所周知的是,火柴棒可以拼成各種各樣的數字。具體可以看下圖:
通過2根火柴棒可以拼出數字“1”,通過5根火柴棒可以拼出數字“2”,以此類推。
現在LYK擁有k根火柴棒,它想將這k根火柴棒恰好用完,並且想知道能拼出的最小和最大的數分別是多少。
輸入格式(stick.in)
一個數k。
輸出格式(stick.out)
兩個數,表示最小的數和最大的數。註意這兩個數字不能有前導0。
輸入樣例
15
輸出樣例
108 7111111
數據範圍
對於30%的數據k<=10。
對於60%的數據k<=20。
對於100%的數據1<k<=100。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int now,anslen=0x7fffffff,ans[101],sum[10]; bool anspre; struct node{ int num,cost,cnt; }q[10]; void dfs(int len,int res){ if(len>anslen)return; if(res==0){ bool flag=0; if(anslen>len)flag=1; if(q[6].cnt==len)return; anslen=len; int lennow=0,ansnow[101]; for(int i=1;i<=7;i++)sum[i]=q[i].cnt; //for(int i=1;i<=7;i++)cout<<sum[i]<<" "; for(int i=2;i<=7;i++){ if(sum[i]){ lennow=lennow+1; ansnow[lennow]=q[i].num,sum[i]--; break; } } for(int i=1;i<=7;i++) while(sum[i]){ lennow=lennow+1; ansnow[lennow]=q[i].num,sum[i]--; } for(int i=1;i<=lennow;i++){ if(ans[i]>ansnow[i]){ flag=1;break; } } if(!anspre)flag=1; //cout<<anslen<<‘ ‘;cout<<endl; if(flag==1){ for(int i=1;i<=anslen;i++)ans[i]=ansnow[i]; anspre=1; } //for(int i=1;i<=anslen;i++)cout<<ansnow[i];cout<<endl; return; } for(int i=1;i<=7;i++){ if(res-q[i].cost>=0){ q[i].cnt++; dfs(len+1,res-q[i].cost); q[i].cnt--; } } } bool cmp(node x,node y){ return x.num<y.num; } int main(){ //freopen("Cola.txt","r",stdin); freopen("stick.in","r",stdin);freopen("stick.out","w",stdout); q[1].num=0,q[1].cost=6; q[2].num=1,q[2].cost=2; q[3].num=2,q[3].cost=5; q[4].num=4,q[4].cost=4; q[5].num=6,q[5].cost=6; q[6].num=7,q[6].cost=3; q[7].num=8,q[7].cost=7; scanf("%d",&now); dfs(0,now); for(int i=1;i<=anslen;i++)printf("%d",ans[i]); printf(" "); if(now%2==1){ int num=(now-3)/2; printf("7"); for(int i=1;i<=num;i++)printf("1"); } else { int num=now/2; for(int i=1;i<=num;i++)printf("1"); } fclose(stdin);fclose(stdout); return 0; }40分 暴力
/* 最大值直接特判一下,最小值用dp解決 dp[i]表示i根火柴能拼出的最小的數字,枚舉該數字末尾的一位是幾 */ #include <cmath> #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> #include <string> #include <cstring> #include <map> #include <vector> #include <set> using namespace std; long long dp[105]; int f[15],n; int main() { freopen("stick.in","r",stdin); freopen("stick.out","w",stdout); f[1]=2; f[2]=5; f[3]=5; f[4]=4; f[5]=5; f[6]=6; f[7]=3; f[8]=7; f[9]=6; f[0]=6; dp[2]=1; dp[3]=7; dp[4]=4; dp[5]=2; dp[6]=6;dp[7]=8; for (int i=8; i<=100; i++) { dp[i]=dp[i-f[0]]*10; for (int j=0; j<=9; j++) if (dp[i-f[j]]!=0) dp[i]=min(dp[i],dp[i-f[j]]*10+j); } cin>>n; cout<<dp[n]<<‘ ‘; if (n%2==1) {cout<<7; n-=3;} while (n){cout<<1; n-=2;} return 0; }100分 動態規劃
聽音樂
(music)
Time Limit:1000ms Memory Limit:128MB
題目描述
LYK喜歡聽音樂,總共有n首音樂,有m個時刻,每個時刻LYK會聽其中一首音樂,第i個時刻會聽第ai首音樂。它給自己定了一個規定,就是從聽音樂開始,聽的每連續n首音樂都是互不相同的。例如當n=3時,從聽歌開始,123321就是一個合法的順序(此時LYK聽了兩輪歌,分別是123和321,每一輪的歌都是互不相同的),而121323就是一個不合法的順序(LYK也聽了兩輪歌,第一輪中121存在聽了兩次相同的歌)。我們現在只截取其中一個片段,也就是說並不知道LYK之前已經聽了什麽歌。因此121323也仍然可以是一個合法的順序,因為LYK之前可能聽過3,然後再聽121323,此時LYK聽了三輪歌,分別是312,132和3。
現在LYK將告訴你這m個時刻它聽的是哪首歌。你需要求出LYK在聽這m首歌之前可能聽過的歌的不同方案總數(我們認為方案不同當且僅當之前聽過的歌的數量不同)。LYK向你保證它之前聽過的歌的數量是在0~n-1之間的。因此你輸出的答案也應當是0~n中的某個整數(答案是0表示LYK記錯了,沒有一個合法的方案)。
輸入格式(music.in)
第一行兩個數n,m。
第二行m個數表示ai。
輸出格式(music.out)
一個數表示答案。
輸入樣例1
4 10
3 4 4 1 3 2 1 2 3 4
輸出樣例1
1
樣例解釋1:LYK之前一定只聽過2首歌(12或者21),這樣可以分成3部分分別是34,4132,1234,每一部分都沒有出現相同的歌。對於其它情況均不滿足條件。
輸入樣例2
6 6
6 5 4 3 2 1
輸出樣例2
6
樣例解釋2:LYK之前聽過0~5首歌的任意幾首都是有可能滿足條件的。
數據範圍
對於50%的數據n,m<=1000。
對於100%的數據1<=n,m<=100000,1<=ai<=n。
其中均勻分布著n<m以及n>=m的情況。
提示:
LYK知道這個題目很長,但為了便於理解已經加了很多註釋了……建議沒看懂的同學們再重新看一遍……
#include<iostream> #include<cstdio> #define maxn 100010 using namespace std; int n,m,a[maxn],ans; bool vis[maxn]; int main(){ //freopen("Cola.txt","r",stdin); freopen("music.in","r",stdin);freopen("music.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++)scanf("%d",&a[i]); for(int i=0;i<n;i++){//枚舉之前聽過的歌的數量 bool flag=0; for(int j=1;j<=n-i;j++){ if(vis[a[j]]){ flag=1; break; } vis[a[j]]=1; } for(int j=1;j<=n-i;j++)vis[a[j]]=0; if(flag)continue; for(int j=n-i+1;j<=m;j+=n){//區間起點 for(int k=j,l=1;k<=m&&l<=n;k++,l++){ if(vis[a[k]]){ flag=1; break; } vis[a[k]]=1; } for(int k=j,l=1;k<=m,l<=n;k++,l++)vis[a[k]]=0; if(flag)break; } if(!flag)ans++; } printf("%d",ans); fclose(stdin);fclose(stdout); return 0; }50分 暴力
2017-10-1 清北刷題沖刺班a.m