日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2019-10-5 NOIP模拟赛多校联考——Round7 题解

發(fā)布時間:2024/1/1 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2019-10-5 NOIP模拟赛多校联考——Round7 题解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

T1 整數(shù)分解

裸的完全背包……被孫到
2i2^i2i當作物品,容量為nnn

#include<stdio.h> #include<cstring> #include<algorithm> #include<math.h> #define re register int #define mod 1000000007 using namespace std; typedef long long ll; int read() {re x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=10*x+ch-'0';ch=getchar();}return x*f; } const int Size=1000005; int n,dp[Size],LOG[Size]; int main() { // freopen("T1.in","r",stdin);n=read();dp[0]=1;for(re i=0; i<=20; i++) {for(re j=0; j+(1<<i)<=n; j++) {dp[j+(1<<i)]=(dp[j+(1<<i)]+dp[j])%mod;}}printf("%d",dp[n]);return 0; }

T2 貧富差距
u,vu,vu,v是朋友就建一條u,vu,vu,v的邊。
如果所有的點都在同一個聯(lián)通塊中,那么貧富差距的最大值就是最長鏈的長度乘以ddd(易證無法構造出更大的貧富差距)。
判-1用并查集,判是否所有的點在同一個聯(lián)通塊中即珂,如果有兩個點不在同一個聯(lián)通塊中,則這兩個點的貧富差距珂以無限擴大。

#include<stdio.h> #include<cstring> #include<algorithm> #include<math.h> #define re register int #define mod 1000000007 using namespace std; int read() {re x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=10*x+ch-'0';ch=getchar();}return x*f; } inline char GetChar() {char ch=getchar();while(ch!='Y' && ch!='N') ch=getchar();return ch; } const int Size=105; int n,d,father[Size]; int Find(int x) {if(x==father[x]) return x;return father[x]=Find(father[x]); } int cnt,head[Size]; struct node {int v,next; } w[Size*Size<<1]; inline void AddEdge(int u,int v) {w[++cnt].v=v;w[cnt].next=head[u];head[u]=cnt; } int Queue[Size],dis[Size]; bool vis[Size]; int bfs(int s) {memset(vis,0,sizeof(vis));int hd=0,tl=0;Queue[++tl]=s;vis[s]=true;dis[s]=0;int ans=0;while(hd<tl) {int x=Queue[++hd];for(re i=head[x]; i; i=w[i].next) {int nxt=w[i].v;if(!vis[nxt]) {vis[nxt]=true;Queue[++tl]=nxt;dis[tl]=dis[hd]+1;if(dis[tl]>ans) {ans=dis[tl];}}}}return ans; } inline void init() {memset(head,0,sizeof(head));cnt=0;for(re i=1; i<=n; i++) {father[i]=i;} } int main() { // freopen("T2.in","r",stdin);int T=read();while(T--) {n=read();d=read();init();for(re i=1; i<=n; i++) {for(re j=1; j<=n; j++) {char ch=GetChar();if(ch=='Y') {AddEdge(i,j);int fx=Find(i);int fy=Find(j);if(fx!=fy) {father[fx]=fy;}}}}int fa=Find(1);bool inf=false;for(re i=2; i<=n; i++) {if(Find(i)!=fa) {inf=true;break;}}if(inf) {puts("-1");continue;}int ans=0;for(re i=1; i<=n; i++) {int now=bfs(i);if(now>ans) {ans=now;}}printf("%d\n",ans*d);}return 0; }

T3 特殊的排列
找出序列上相鄰兩項差為1的最長子序列,則這個子序列長度是最長的不用移動的長度。
證明:
1.移動一個子序列之外的數(shù),子序列的相對順序不變。
2.不在最長子序列中的數(shù)一定要移動到序列首或序列末(否則珂以形成更長的相鄰兩項差為1的子序列)。
3.不存在另一個更長的子序列,相鄰兩項差不為1,且這個子序列中的數(shù)不用移動。因為若相鄰兩項差不為1,那么這兩項之間的數(shù)必須要通過移動子序列里的數(shù)來得到。

#include<stdio.h> #include<cstring> #include<algorithm> #include<math.h> #define re register int using namespace std; int read() {re x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f; } const int Size=50005; int dp[Size]; int main() {int n=read();int ans=0;for(re i=1; i<=n; i++) {int x=read();if((dp[x]=dp[x-1]+1)>ans) {ans=dp[x];}}printf("%d",n-ans);return 0; }

T4 極品飛車
一個特殊的隱含條件是速度必須要>0,否則時間會變成負數(shù)或正無窮(長者:只有我才能操控負數(shù)和+∞+\infin+的時間,你們還是太naive)
列出式子,d1s1+c+d2s2+c+...+dnsn+c=t\frac{d_1}{s_1+c}+\frac{d_2}{s_2+c}+...+\frac{d_n}{s_n+c}=ts1?+cd1??+s2?+cd2??+...+sn?+cdn??=t
因為對于任意iii,有si+c>0s_i+c>0si?+c>0,所以左邊是單調遞減的。
所以二分ccc,暴力判即珂。

#include<stdio.h> #include<cstring> #include<algorithm> #include<math.h> #define re register int #define mod 1000000007 #define eps 1e-10 using namespace std; int read() {re x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=10*x+ch-'0';ch=getchar();}return x*f; } inline char GetChar() {char ch=getchar();while(ch!='Y' && ch!='N') ch=getchar();return ch; } const int Size=1005; int n; double t,s[Size],d[Size]; double check(double mid) {double ans=0;for(re i=1; i<=n; i++) {if(fabs(s[i]+mid)<eps) {ans+=1e15;} else {ans+=d[i]/(s[i]+mid);}}return ans; } int main() { // freopen("T4.in","r",stdin);n=read();scanf("%lf",&t);double minn=1e10;for(re i=1; i<=n; i++) {scanf("%lf %lf",&d[i],&s[i]);if(s[i]<minn) minn=s[i];}double l=-minn+eps,r=1e7,mid;for(re i=1; i<=1000; i++) {mid=(l+r)/2;if(check(mid)>=t) {l=mid;} else {r=mid;}}printf("%.6lf",l);return 0; } /* 3 9 3 2 6 3 9 4 */

T5 修改數(shù)組
首先把所有a[i]a[i]a[i]都減去iii,然后題目變成修改一些數(shù),要求改成非負整數(shù),且滿足序列不減。
把所有a[i]>=0a[i]>=0a[i]>=0a[i]a[i]a[i]提取出來,跑最長不降子序列。因為序列不減,所以剩下的a[i]<0a[i]<0a[i]<0的部分一定能改成一個非負整數(shù),使序列不減。
最后只有這個LIS的所有元素不用修改。

#include<stdio.h> #include<cstring> #include<algorithm> #include<math.h> #define re register int using namespace std; int read() {re x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f; } const int Size=100005; int n,maxn,a[Size],b[Size],tree[Size]; inline int lowbit(int x) {return x&(-x); } inline void update(int x,int v) {for(re i=x; i<=maxn; i+=lowbit(i)) {if(v>tree[i]) {tree[i]=v;}} } inline int query(int x) {int ans=0;for(re i=x; i; i-=lowbit(i)) {if(tree[i]>ans) {ans=tree[i];}}return ans; } int main() {n=read();int tot=0;for(re i=1; i<=n; i++) {a[i]=read()-i;if(a[i]>=0) {b[++tot]=a[i];}}for(re i=1; i<=tot; i++) {a[i]=b[i];}sort(a+1,a+1+tot);maxn=unique(a+1,a+1+tot)-(a+1);for(re i=1; i<=tot; i++) {b[i]=lower_bound(a+1,a+1+maxn,b[i])-a;}int ans=0;for(re i=1; i<=tot; i++) {int x=query(b[i]);update(b[i],x+1);if(x+1>ans) {ans=x+1;}}printf("%d",n-ans);return 0; } /* 12 3 3 6 6 1 2 6 1 1 3 6 4 */

T6 小Biu看電影
不知道為什么珂以暴力dfs……

#include<stdio.h> #include<cstring> #include<algorithm> #include<math.h> #define re register int #define mod 1000000007 using namespace std; int read() {re x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=10*x+ch-'0';ch=getchar();}return x*f; } const int Size=300005; const int INF=0x3f3f3f3f; int n,m,cnt,head[Size]; struct Edge {int v,t,next; } w[Size<<1]; void AddEdge(int u,int v,int c) {w[++cnt].v=v;w[cnt].t=c;w[cnt].next=head[u];head[u]=cnt; } int ans=INF,val[Size],dis[Size]; void dfs(int x,int sum) {if(sum>=ans) return;if(sum+val[x]<ans) {ans=sum+val[x];}for(int i=head[x]; i; i=w[i].next) {int nxt=w[i].v;if(sum+w[i].t<dis[nxt]) {dis[nxt]=sum+w[i].t;dfs(nxt,sum+w[i].t);}} } int main() { // freopen("T6.in","r",stdin);n=read();m=read();for(re i=1; i<=n; i++) {val[i]=read();}for(re i=1; i<=m; i++) {int u=read();int v=read();int c=read()<<1;AddEdge(u,v,c);AddEdge(v,u,c);}for(re i=1; i<=n; i++) {memset(dis,0x3f,sizeof(dis));ans=val[i];dfs(i,0);printf("%d\n",ans);}return 0; }

正解:
建一個虛點sss,從sss向所有iii連邊權為val[i]val[i]val[i]的邊,跑dijkstra。
然后sss到每個點的距離就是從這個點開始能看到電影的最小花費(容易看出最小花費就是sss到一個點的最短距離,因為一開始建了邊權為val[i]val[i]val[i]的邊)。

#include<stdio.h> #include<cstring> #include<algorithm> #include<queue> #define re register int #define mod 1000000007 using namespace std; int read() {re x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=10*x+ch-'0';ch=getchar();}return x*f; } const int Size=100005; const int INF=0x3f3f3f3f; int n,m,cnt,head[Size]; struct Edge {int v,t,next; } w[600005]; void AddEdge(int u,int v,int c) {w[++cnt].v=v;w[cnt].t=c;w[cnt].next=head[u];head[u]=cnt; } struct node {int x,t; }; inline bool operator < (const node a,const node b) {return a.t>b.t; } int dis[Size]; void Dijkstra(int s) {memset(dis,0x3f,sizeof(dis));priority_queue<node> Q;Q.push((node){s,0});dis[s]=0;while(!Q.empty()) {int x=Q.top().x;Q.pop();for(re i=head[x]; i; i=w[i].next) {int nxt=w[i].v;if(dis[x]+w[i].t<dis[nxt]) {dis[nxt]=dis[x]+w[i].t;Q.push((node){nxt,dis[nxt]});}}} } int main() { // freopen("T6.in","r",stdin);n=read();m=read();int s=n+1;for(re i=1; i<=n; i++) {int x=read();AddEdge(s,i,x);}for(re i=1; i<=m; i++) {int u=read();int v=read();int c=read()<<1;AddEdge(u,v,c);AddEdge(v,u,c);}Dijkstra(s);for(re i=1; i<=n; i++) {printf("%d\n",dis[i]);}return 0; }

總結

以上是生活随笔為你收集整理的2019-10-5 NOIP模拟赛多校联考——Round7 题解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。