1. 程式人生 > >【自家測試】2017.12.3

【自家測試】2017.12.3

image lib 註意 答案 處理 soft sap b+ char

T1

技術分享圖片

技術分享圖片

卡死在T1。

打了兩個小時數位dp,結果tmd是道結論題。

∵d(x)==x%9

∴喜歡的數一定可以寫成(x*9+b)*b==9*x*b+b*b的形式

b從1~9,把d*d按模9的余數分類算一下,然後容斥一下即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define LL long long

LL calc(LL x) {
	LL res=0,a,b;
	if(x>=1) res+=(x-1)/9+1; 
	a=x>=4?(x-4)/18+1:0; b=x>=49?(x-49)/63+1:0;
	res=res+a+b-a/7;
	a=x>=16?(x-16)/36+1:0LL; b=x>=25?(x-25)/45+1:0;
	res=res+a+b-a/5;
	a=x>=9?(x-9)/27+1:0LL; b=x>=36?(x-36)/54+1:0;
	if(x>=81) res+=x/81;
	res=res+a+b-a/2;
	return res;
}

int main()
{
  int T;
  LL l,r;
  scanf("%d",&T);
  while(T--)
  {
    scanf("%lld%lld",&l,&r);
    printf("%lld\n",calc(r)-calc(l-1)); 
  }
  return 0;
}

  

忘了return然後wa成傻逼

T2

技術分享圖片

一個因為數據水可以過的歪解

因為可以發現最小路徑上顯然每個點只會經過一次

只要只要不從從一出去的這條路再走回來即可

枚舉每條出去的邊,刪掉它的反向邊,跑spfa

數據很水,加個slf優化就過了90.第一個點比較毒不管。

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
const int N=10005;
const int M=400007;
typedef long long LL;
using namespace std;

int n,m;

template<typename T> void read(T &x) {
	char ch=getchar(); x=0; T f=1;
	while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
	if(ch==‘-‘) f=-1,ch=getchar();
	for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; x*=f;
}

int ecnt=1,fir[N],nxt[M],to[M],val[M];
void add(int u,int v,int w) {
	nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
}

deque<int>que;
int vis[N],dis[N];
int spfa(int idd) {
	memset(dis,127/3,sizeof(dis));
	dis[to[idd]]=0; vis[to[idd]]=1;
	que.push_back(to[idd]);
	while(!que.empty()) {
		int x=que.front();
		que.pop_front();
		vis[x]=0;
		for(int i=fir[x];i;i=nxt[i]) if(i!=(idd^1)) {
			int y=to[i];
			if(dis[y]>dis[x]+val[i]) {
				dis[y]=dis[x]+val[i];
				if(!vis[y]) {
					vis[y]=1;
					if(!que.empty()) {
						int tp=que.front();
						if(dis[y]<dis[tp]) que.push_front(y); 
						else que.push_back(y);   
					}
					else que.push_back(y);  
				} 
			}	
		}
	} 
	return val[idd]+dis[1];
}

void work() {
	int ans=1e9+7;
	for(int i=fir[1];i;i=nxt[i]) {
		ans=min(ans,spfa(i));
	}
	printf("%d\n",ans);
}

void init() {
	read(n); read(m);
	for(int i=1;i<=m;i++) {
		int u,v,w,ww;
		read(u); 
		read(v);
		read(w);
		read(ww);
		add(u,v,w);
		add(v,u,ww);
	}
}

int main() {
#ifdef DEBUG
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
#endif
	init();
	work();
	return 0;
}
/*
3 3
1 2 2 1
2 3 4 5
3 1 3 2
*/

T3

好像T2,T3搞反了,無所謂了。

技術分享圖片

二分答案跑有上下界的網絡流。

設現在check的答案為ans

源點向每一行連上界為sumh[i]+ans,下界為max(sumh[i]-ans,0)的邊

每一行向每一列連上界R下界L的邊

每一列向匯點連上界為suml[i]+ans,下界為max(suml[i]-ans,0)的邊

註意超級源點和超級匯點的處理方法,每個點是出流減入流,然後記得匯點向源點連inf的邊

最後判斷超級源點的邊是否滿流即可

又驗證了一下ISAP的優越性

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
#define inf 0x7fffffff
const int N=405;
typedef long long LL;
using namespace std;

int n,m,L,R,tot,lim,a[N][N],b[N][N],sumh[N],suml[N];

template<typename T> void read(T &x) {
	char ch=getchar(); x=0; T f=1;
	while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
	if(ch==‘-‘) f=-1,ch=getchar();
	for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; x*=f;
}

struct edge {
	int from,to,cap,flow,nxt;
	edge() {}
	edge(int from,int to,int cap,int flow,int nxt):from(from),to(to),cap(cap),flow(flow),nxt(nxt) {}
}e[N*N*2];

int ecnt=1,fir[N],cur[N];
void add(int u,int v,int w) {	
	e[++ecnt]=edge(u,v,w,0,fir[u]); fir[u]=ecnt;
	e[++ecnt]=edge(v,u,0,0,fir[v]); fir[v]=ecnt;
}

int d[N],c[N],p[N],ve[N];
queue<int>que;
void bfs(int s,int t) {
	for(int i=1;i<=tot;i++)  d[i]=tot,c[i]=0;
	d[t]=0; que.push(t);
	while(!que.empty()) {
		int x=que.front();
		que.pop();
		for(int i=fir[x];i;i=e[i].nxt) {
			int y=e[i].to;
			if(d[y]==tot&&e[i].flow==e[i].cap) {
				d[y]=d[x]+1;
				que.push(y); 
			} 
		}
	}
	return;
}

int cal(int s,int t) {
	int res=inf;
	for(int x=t;x!=s;x=e[p[x]].from) 
		res=min(res,e[p[x]].cap-e[p[x]].flow);
	for(int x=t;x!=s;x=e[p[x]].from) {
		e[p[x]].flow+=res;
		e[p[x]^1].flow-=res;
	}
	return res;
}
 
int ISAP(int s,int t) {
	bfs(s,t);
	int res=0;
	for(int i=1;i<=tot;i++) cur[i]=fir[i],c[d[i]]++;
	for(int x=s;d[x]<tot;) {
		if(x==t) {
			res+=cal(s,t);
			x=s;
		}
		int ok=0;
		for(int &i=cur[x];i;i=e[i].nxt) {
			int y=e[i].to;
			if(d[y]+1==d[x]&&e[i].cap>e[i].flow) {
				p[x=y]=i; ok=1; break;
			}
		}
		if(!ok) {
			cur[x]=fir[x];
			int M=tot;
			for(int i=fir[x];i;i=e[i].nxt) {
				int y=e[i].to;
				if(e[i].cap>e[i].flow) M=min(M,d[y]+1); 
			}
			if(M==tot) break;
			if(!(--c[d[x]])) break;
			c[d[x]=M]++;
			if(x!=s) x=e[p[x]].from;
		}
	}
	return res;
}

void clear() {
	memset(fir,0,sizeof(fir));	
	ecnt=1; lim=0;
	memset(ve,0,sizeof(ve));
}

int check(int ans) {
	clear();
	int s=n+m+1,t=s+1,ss=t+1,tt=ss+1;
	tot=tt;
	for(int i=1;i<=n;i++) {
		int up=(ans+sumh[i]),dn=max(0,sumh[i]-ans);
		add(s,i,up-dn);
		ve[s]+=dn;
		ve[i]-=dn;
	}
	for(int i=1;i<=m;i++) {
		int up=(ans+suml[i]),dn=max(0,suml[i]-ans);
		add(n+i,t,up-dn);
		ve[n+i]+=dn;
		ve[t]-=dn;
	}
	for(int i=1;i<=n;i++) 
		for(int j=1;j<=m;j++) {
			int up=R,dn=L;
			add(i,n+j,up-dn);
			ve[i]+=dn;
			ve[n+j]-=dn;
		}
	for(int i=1;i<=tot;i++) {
		if(ve[i]>0) add(i,tt,ve[i]);
		else if(ve[i]<0) { add(ss,i,-ve[i]); lim-=ve[i];}
	}
	add(t,s,inf);
	return ISAP(ss,tt)>=lim;
}

void work() {
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			sumh[i]+=a[i][j];
			
	for(int j=1;j<=m;j++)
		for(int i=1;i<=n;i++)
			suml[j]+=a[i][j];	
			 
	int l=0,r=2e5,ans=r;
	while(l<=r) {
		int mid=(l+r)>>1;
		if(check(mid)) ans=mid,r=mid-1;
		else l=mid+1; 
	}
	
	check(ans);
	printf("%d\n",ans);
	for(int i=1;i<=n;i++) 
		for(int j=fir[i];j;j=e[j].nxt) 
			if(e[j].to>=n+1&&e[j].to<=n+m) 
				b[i][e[j].to-n]=e[j].flow+L;
				
	for(int i=1;i<=n;i++) {
		for(int j=1;j<m;j++)
			printf("%d ",b[i][j]);
		printf("%d",b[i][m]);	
		printf("\n");
	}	
}

void init() {
	read(n); read(m); 
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++) 
			read(a[i][j]);
	read(L); read(R);
}

int main() {
#ifdef DEBUG
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
#endif
	init();
	work();
	return 0;
}
/*
2 2 
0 1
2 1
0 1
*/

  

【自家測試】2017.12.3