不要问我8.19的题为什么今天才写完,因为我弱啊
T1 扫雷(mine)
Solution:
显然,(ans = min_{i=1}^n frac{bi}{ai}),令cnt为满足ans的个数,方案数即(2^{cnt }-1),用快速幂来求。
另外,本题卡精度,你当然可以向XMJJSW一样写一个分数类,也可以对输入的数成(10^8), 用整形判断
不过最方便的还是设个eps,取个1e-12
即可以了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define MN 1000005
double a[MN],b[MN];
long long num,n,ans;
#define mod 998442553
#define eps 1e-12
#define sign(a) ((a>(-eps))-(a<eps))
inline bool cmp(const int&x,const int&y){
return sign(a[x]*b[y]-b[x]*a[y])==1;
}
long long Quick_pow(long long m,long long p){
long long res=1;
while(p){
if(p&1) res=(res*m)%mod,p-=1;
else m=(m*m)%mod,p>>=1;
}
return res;
}
int main(){
freopen("mine.in","r",stdin);
freopen("mine.out","w",stdout);
int T;scanf("%d
",&T);
while(T--){
scanf("%d",&n);register int i;
for(i=1;i<=n;i++) scanf("%lf",&a[i]);
for(i=1;i<=n;i++) scanf("%lf",&b[i]);
ans=1;num=0;
for(i=2;i<=n;i++) if(cmp(i,ans)) ans=i;
for(i=1;i<=n;i++){
if(sign(a[i]*b[ans]-a[ans]*b[i])==0) num++;
}
if(sign(b[ans]-a[ans]*10000.0)==1){
puts("Impossible");continue;
}
num=(Quick_pow(2,num)+mod-1)%mod;
printf("%.8lf %lld
",b[ans]/a[ans],num);
}
return 0;
}
T2 信息组的裁员(cut)
Solution:
对于30%的数据,可以使用O((m^2))的简单dp。
对于60%的数据,可以贪心,也很好想。
对于100%的数据,考虑贪心的优化。
官方题解:
嗯,完美。
//30分的dp
#include<iostream>
#include<cstdio>
#include<algorithm>
inline long long read(){
long long 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;
}
#define MN 6000005
long long n,m,a[MN],q[MN];
long long num,sum,f[2][MN];
int main(){
freopen("cut.in","r",stdin);
freopen("cut.out","w",stdout);
n=read();m=read();
register int i,j;
for(i=1;i<=n;i++) a[i]=read(),q[i]=q[i-1]+a[i];
for(i=1;i<=n;i++) if(a[i]>=0){
j=i;num++;while(a[i+1]>=0&&i<n) i++;
sum+=q[i]-q[j-1];
}
if(num<=m) return 0*printf("%lld
",sum);
int now=1,last=0;
for(i=1;i<=n-m+1;i++) f[0][i]=std::max(f[0][i-1],q[i]);
for(i=2;i<=m;i++){
f[now][i]=q[i];
for(j=i+1;j<=i+n-m;j++) f[now][j]=a[j]+std::max(f[now][j-1],f[last][j-1]);
for(j=i+1;j<=i+n-m;j++) f[now][j]=std::max(f[now][j-1],f[now][j]);
now^=1;last^=1;
}
printf("%lld
",f[last][n]);
return 0;
}
#include<bits/stdc++.h>
inline int read(){
int 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<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define abs(a) (((a)>0)?(a):-(a))
#define cmin(a,b) (a>(b)?a=(b),1:0)
#define cmax(a,b) (a<(b)?a=(b),1:0)
#define dmin(a,b) ((a)<(b)?(a):(b))
#define dmax(a,b) ((a)>(b)?(a):(b))
typedef long long ll;
#define MN 6000005
struct data{
ll val;int pos;
data(ll v=0,int p=0){val=v;pos=p;}
bool operator< (const data &o) const{return val<o.val||val==o.val&&pos<o.pos;}
bool operator<=(const data &o) const{return val<o.val||val==o.val&&pos<=o.pos;}
}t[MN],mx,mx2;
ll a[MN],ans;
int remain,n,m,q[MN],hq,tq,cnt,l[MN],r[MN],L[MN],R[MN];
bool inq[MN],del[MN],Del[MN];
void AddQue(int i){
if(i&&(!inq[i])&&data(abs(a[i]),i)<=mx) q[++tq]=i,inq[i]=true;
}
void dele(int x){
if((!x)||del[x]) return ;
r[l[x]]=r[x];l[r[x]]=l[x];
del[x]=true;
}
void Dele(int x){
if((!x)||Del[x]) return ;
remain--;R[L[x]]=R[x];L[R[x]]=L[x];
Del[x]=true;dele(x);
}
void Merge(int x){
if(Del[x]) return ;
int lef=L[x],rig=R[x];
if(lef&&abs(a[lef])<abs(a[x])) return ;
if(rig&&abs(a[rig])<abs(a[x])) return ;
Dele(lef);Dele(rig);a[x]+=a[lef]+a[rig];
lef&&rig?AddQue(x):Dele(x);
AddQue(lef);AddQue(rig);
}
int main(){
freopen("cut.in","r",stdin);
freopen("cut.out","w",stdout);
n=read();m=read();int i,j,x;
for(i=1,j=0;i<=n;i++){
a[++j]=read();if(a[j]==0||j==1&&a[j]<0)--j;
if(j>1&&(a[j]>0)^(a[j-1]<0)) a[j-1]+=a[j],--j;
}if(j>0&&a[j]<0) --j;
for(i=0;i<=j;i++)
r[i]=R[i]=(i+1)%(j+1),l[i]=L[i]=(i+j)%(j+1);
remain=j;
while(1){
cnt=0;hq=1;tq=0;
for(i=r[0];i;i=r[i]) t[++cnt]=data(abs(a[i]),i);
if(remain<(m<<1)) break;
int mid=(remain-(m<<1)+1)>>1;
std::nth_element(t+1,t+dmin(mid,cnt)+1,t+cnt+1);
mx=t[dmin(mid,cnt)];
std::nth_element(t+1,t+dmin(mid*3,cnt)+1,t+cnt+1);
mx2=t[dmin(mid*3,cnt)];
for(i=r[0];i;i=r[i]){
data cur(abs(a[i]),i);
if(mx2<cur) dele(i);
else AddQue(i);
}
for(;hq<=tq;++hq)
inq[q[hq]]=false,Merge(q[hq]);
}ans=0;
for(i=R[0];i;i=R[i]) if(a[i]>0) ans+=1ll*a[i];
printf("%lld
",ans);
return 0;
}
T3 已傻的结合(ishhac)
Solution:
-
dp方程:(a=0的时候)
[f_{k,i,j}=min_{x}^n max {f_{k-1,i,x},g_{x,j}}$$其中,`g[x][j]`表示x到j的边权。 ] -
因为T<=4,所以图的一个周期是12,所以$$G_i=G_{i mod 12}$$.
分别求出这12个矩阵,命名为
A1~A12
,则最终矩阵是[R= A_{12}^{leftlfloorfrac{K}{12} ight floor}Phi A_{K mod 12} ]用矩阵快速幂求(A_{12}^{leftlfloorfrac{K}{12} ight floor})即可。
膜一下大佬的代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int inf = 0x3f3f3f3f;
typedef long long LL;
LL ri() {
char c = getchar(); LL x = 0; for(;c < '0' || c > '9'; c = getchar()) ;
for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x;
}
struct Maxtir {
int n, m[60][60];
void Init() {n = 0; std::memset(m, 0x3f, sizeof(m));}
Maxtir operator * (Maxtir a) {
Maxtir b; b.n = a.n;
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= n; ++j) {
b.m[i][j] = inf;
for(int k = 1;k <= n; ++k)
b.m[i][j] = std::min(b.m[i][j], std::max(a.m[k][j], m[i][k]));
}
return b;
}
}a, b, c[13];
int n, m, s, t; LL K;
void Pow(Maxtir &a, LL x) {Maxtir b = a; x--; for(;x; b = b * b, x >>= 1) if(x & 1) a = a * b;}
int main() {
freopen("ishaac.in","r",stdin);
freopen("ishaac.out","w",stdout);
for(int C = ri(); C--;) {
a.Init(); n = ri(); m = ri(); s = ri(); t = ri(); K = ri(); a.n = n;
for(int i = 1, u, v, w;i <= m; ++i)
u = ri(), v = ri(), w = ri(), a.m[u][v] = a.m[v][u] = w;
for(int i = 1;i <= 12; ++i) c[i] = a;
int nf = ri();
for(int i = 1, T, j, x, k;i <= nf; ++i)
for(T = ri(), j = 0;j < T; ++j)
for(x = ri(), k = j;k <= 12; k += T)
for(int p = 1;p <= n; ++p)
c[k].m[p][x] = inf;
a = c[1];
if(K <= 12) {
for(int i = 2;i <= K; ++i) a = a * c[i];
a.m[s][t] == inf ? puts("impossible") : printf("%d
", a.m[s][t]);
continue;
}
for(int i = 2;i <= 12; ++i) a = a * c[i];
Pow(a, K / 12);
for(int i = 1;i <= K % 12; ++i) a = a * c[i];
a.m[s][t] == inf ? puts("impossible") : printf("%d
", a.m[s][t]);
}
return 0;
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!