T1:
固定一个方向的刀数的时候,平均切时答案最大。
可以发现,如果能够只切一边,只切一边一定最优。
当n<=m,k>=m时,考虑将一边全部切开,剩下的平均切到另一边。
因为n/(k-(n-1))>=m/(k-(m-1)),所以长边切m-1刀,短边切k-(m-1)刀一定最优。
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll long long 5 using namespace std; 6 inline ll in(){ 7 ll x=0;bool f=0; char c; 8 for (;(c=getchar())<'0'||c>'9';f=c=='-'); 9 for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); 10 return f?-x:x; 11 } 12 ll n,m,k; 13 int main() 14 { 15 n=in();m=in();k=in(); 16 if (n<m) swap(n,m); 17 if (k>n+m-2) {printf("-1");return 0;} 18 if (k<m) printf("%lld",max((m/(k+1))*n,(n/(k+1))*m)); 19 else if (k<n) printf("%lld",max(n/(k-m+2),(n/(k+1))*m)); 20 else printf("%lld",max(n/(k-m+2),m/(k-n+2)));return 0; 21 }
T2:注意到ai不超过30,所以选择的bi小于59,否则选择1一定不劣。
注意到58以内只有16个质数,考虑将选择这些质数的状态压缩后dp即可,时间复杂度O(2^16*n*58).
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define inf 0x3f3f3f3f 5 #define MN 102 6 #define Range 59 7 #define Rp 16 8 using namespace std; 9 inline int in(){ 10 int x=0;bool f=0; char c; 11 for (;(c=getchar())<'0'||c>'9';f=c=='-'); 12 for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); 13 return f?-x:x; 14 } 15 const int pri[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53}; 16 int f[MN][(1<<Rp)],pre[MN][(1<<Rp)],a[MN],s[Range],st[MN]; 17 int n,mn=inf,p=0; 18 int main() 19 { 20 n=in();for (int i=1;i<=n;++i) a[i]=in(); 21 memset(f,0x3f,sizeof(f));f[0][0]=0; 22 for (int i=1;i<Range;++i) 23 for (int j=0;j<Rp;++j) if (!(i%pri[j])) s[i]|=(1<<j); 24 for (int i=1;i<=n;++i) 25 for (int j=0;j<(1<<Rp);++j) 26 for (int k=1;k<Range;++k) 27 if (!(j&s[k])&&f[i][j|s[k]]>f[i-1][j]+abs(a[i]-k)) 28 f[i][j|s[k]]=f[i-1][j]+abs(a[i]-k),pre[i][j|s[k]]=k; 29 for (int i=0;i<(1<<Rp);++i) if (f[n][i]<mn) mn=f[n][i],p=i; 30 for (int i=n;i;p^=s[pre[i][p]],--i) st[i]=pre[i][p]; 31 for (int i=1;i<=n;++i) printf("%d ",st[i]);return 0; 32 }
T3:对新加边去重,对于每个点的边只保留边权最小的边,然后做最短路。
一条新加边如果长度不是到该点最短路的长度一定可以去掉,否则只有满足有其它最短路径到达这个点的时候才可以去掉。
因此算出到每个点最短路条数是否大等于2即可。
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #define mp(x,y) make_pair(x,y) 6 #define ll long long 7 #define inf 0x3f3f3f3f 8 #define ME 500005 9 #define MN 50005 10 using namespace std; 11 inline int in(){ 12 int x=0;bool f=0; char c; 13 for (;(c=getchar())<'0'||c>'9';f=c=='-'); 14 for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); 15 return f?-x:x; 16 } 17 struct edge{ 18 int to,next; 19 ll val; 20 }e[ME]; 21 int head[MN],num[MN],n,m,k,s,u,v,cnt=0,res; 22 ll dis[MN],dst[MN],t,w; 23 inline void ins(int x,int y,ll v){ 24 e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt;e[cnt].val=v; 25 } 26 typedef pair<ll,int> pr; 27 inline void dij(int s){ 28 priority_queue<pr,vector<pr>,greater<pr> > q; 29 memset(dis,0x3f,sizeof(dis)); 30 dis[s]=0ll;q.push(mp(0ll,s)); 31 while (!q.empty()){ 32 pr x=q.top();int u=x.second;q.pop(); 33 if (dis[u]<x.first) continue; 34 for (int i=head[u];i;i=e[i].next){ 35 int v=e[i].to; 36 if (dis[v]>dis[u]+e[i].val){ 37 dis[v]=dis[u]+e[i].val; 38 q.push(mp(dis[v],v));num[v]=num[u]; 39 }else if (dis[v]==dis[u]+e[i].val) num[v]=min(num[u]+num[v],inf); 40 } 41 } 42 } 43 int main() 44 { 45 n=in();m=in();k=in(); 46 for (int i=1;i<=m;++i){ 47 u=in();v=in();scanf("%lld",&t); 48 ins(u,v,t);ins(v,u,t); 49 }for (int i=1;i<=k;++i){ 50 s=in();scanf("%lld",&w); 51 if (dst[s]) ++res,dst[s]=min(dst[s],w); 52 else dst[s]=w; 53 }for (int i=2;i<=n;++i) 54 if (dst[i]) ins(1,i,dst[i]),ins(i,1,dst[i]);dij(1); 55 for (int i=2;i<=n;++i){ 56 if (dst[i]&&(dis[i]<dst[i]||(dis[i]==dst[i]&&num[i]>1))) ++res; 57 }printf("%d",res);return 0; 58 }