2019.07.04【NOIP提高组】模拟 A 组 比赛总结

题目

非回文数字

Description

如果一个字符串从后往前读与从前往后读一致,我们则称之为回文字符串。当一个数字不包含长度大于1的子回文数字时称为非回文数字。例如,16276是非回文数字,但17276不是,因为它包含回文数字727。
你的任务是在一个给定的范围内计算非回文数字的总数。

Input

输入仅一行,包含两个整数a和b。

Output

输出仅一行,包含一个整数,表示a到b范围内(包括a和b)非回文数字的总数。

Sample Input

输入1:
123 321
输入2:
123456789 987654321

Sample Output

输出1:
153
输出2:
167386971

Data Constraint

25%的数据:b-a<=100 000.
100%的数据:0<=a<=b<=10^18


管道

Description

Hotham市再次被Jester袭击。这一次,Jester攻击的目标是Hotham的供水系统。Hotham的淡水存储在N个水库,由M个管道连接。
任意2个水库之间至少有一条路径,该路径可能包含多个管道。每个管道连接两个不同的水库,任何两个水库之间最多只有一个管道。Jester破坏了一些管道进行排水。管道的排水量为偶数立方米/秒。如果连接水库u和水库v的管道排水量为2D立方米/秒,那么水库u和水库v排水量分别为D立方米/秒。Jester可以也破坏一些管道进行注水。同样,连接水库u和v的管道注入水量为2P立方米/秒,则水库u和水库v注水量分别为P立方米/秒。
每个水库供水量的净变化是由连接到它的管道的排水量和注水量的总和。如果连接该水库的管道排水量分别为2D1, 2D2,…,2Da立方米/秒, 注水量分别为2P1, 2P2 ,…,2Pb 立方米/秒。该水库水量的净变化为P1 + P2 + … + Pb -D1 - D2 –Da。
Hotham市长已在水库安装了传感器,但不是在管道中。因此,他可以观察到在每个水库水的净变化,但并知道有多少水被排出或注入各个管道。
给出水管连接图和每个水库供水量的净变化,编写程序决定这些信息是否能确定一个唯一的计划。如果各个水管排出或注入的水量是唯一的,那么该计划可以被唯一确定。请注意,并不是每一个水管中的注水量和排水量都相等。如果恰好有一个可能性,你的程序应该打印出来。

Input

输入的第一行包含两个整数:N:Hotham的水库数 和M:管道数。
接下来的N行每行包含一个整数ci:表示水库i(1≤i≤N)的水量净变化。
再接下来的M行每行包含两个整数ui和vi(1≤i≤M)。每一行分别表示,水库 ui和vi之间有管道连接(1≤ui,vi≤N)。

Output

如果Jester的计划不能被唯一确定,你的程序则输出0。否则,你的程序应该输出M行,每一行包含一个整数Xi(1≤i≤M)。 如果Jester从连接水库ui和vi间的管道里排水,该管道的排水量为di立方米/秒,则设Xi=-di。如果Jester往连接水库ui和vi间的管道里注水,该管道的注水量为pi立方米/秒,则Xi=pi。如果Jester对连接水库ui和vi间的管道既不排水也不注水,则Xi =0。

Sample Input

输入1:
4 3
-1
1
-3
1
1 2
1 3
1 4
输入2:
4 5
1
2
1
2
1 2
2 3
3 4
4 1
1 3

Sample Output

输出1:
2
-6
2
输出2:
0

Data Constraint

1<=N<=100 000
1<=M<=500 000
− 1 0 9 &lt; = C i &lt; = 1 0 9 -10^9&lt;=C_i&lt;=10^9 109<=Ci<=109
如果方案唯一,则 − 1 0 9 &lt; = X i &lt; = 1 0 9 -10^9&lt;=X_i&lt;=10^9 109<=Xi<=109
30%的数据满足供水系统的网络是一棵树。


牛棚安排

Description

Farmer John的N(1<=N<=1000)头奶牛分别居住在农场所拥有的B(1<=B<=20)个牛棚的某一个里。有些奶牛很喜欢她们当前住的牛棚,而另一些则讨厌再在它们现在所在的牛棚呆下去。
FJ在忍受了若干次奶牛的抱怨后,决定为所有奶牛重新安排牛棚,使最不满的那头奶牛与最高兴的奶牛的心情差异最小,即使这会让所有奶牛都更加郁闷。
每头奶牛都把她对各个牛棚的好感度从高到低排序后告诉了FJ。当然,如果一头奶牛被安排到的牛棚在她给出的列表中越靠后,她就会越郁闷。你可以认为奶牛的郁闷指数是她被分配到的牛棚在列表中的位置。奶牛们是斤斤计较的,她们无法容忍别的奶牛在自己喜欢的牛棚里快乐地生活,而自己却呆在一个自己不喜欢的牛棚里。每个牛棚都只能容纳一定数量的奶牛。FJ希望在每个牛棚都没有超出容量限制的前提下,使最郁闷和最高兴的奶牛的郁闷指数的跨度最小。
FJ请你帮他写个程序,来计算这个最小的郁闷指数跨度到底是多少。

Input

第1行: 包含2个用空格隔开的整数N和B,分别表示牛和牛棚的数量
第2…N+1行: 每行包含B个用空格隔开的整数,刚好完全包含1…B的整数。第i+1行的第一个整数,表示奶牛i最喜欢的牛棚编号。第二个整数表示奶牛i的列表中排在第二位,也就是她第二喜欢的牛棚。依此类推。
第N+2行: 包含B个用空格隔开的整数,第i个整数表示牛棚i最多能容纳的奶牛的数目。所有牛棚能容纳奶牛头数的和至少是N。

Output

第1行: 输出一个整数,表示所有奶牛中最高兴与最郁闷的牛的郁闷指数跨度

Sample Input

6 4
1 2 3 4
2 3 1 4
4 2 3 1
3 1 2 4
1 3 4 2
1 4 2 3
2 1 3 2

Sample Output

2

Hint

【样例说明】
每头奶牛都能被安排进她的第一或第二喜欢的牛棚。下面给出一种合理的分配方案:奶牛1和奶牛5住入牛棚1,牛棚2由奶牛2独占,奶牛4住进牛棚3,剩下的奶牛3和奶牛6安排到牛棚4。


总结

今天的题目总体比较水,但我的得分也比较低。
P.S:今天的T1本来是3315. 【BOI2013】球树的,但是这题与昨天的T1几乎一模一样,于是XC很高效地用了0.5个小时换了题。
原题如下:
在这里插入图片描述
先看了一遍题目,感觉T2很烦不想弄,T3不会做,但是我看到了这样的一句话:

30%的数据满足供水系统的网络是一棵树。

于是画了画,发现这种情况可以从叶子结点往上推。
再看T1(此时已换题),发现好像很简单耶!于是推了半天,发现可以二分+网络流搞定,时间复杂度 O ( m log ⁡ 2 m n 2 ) O(m\log_2mn^2) O(mlog2mn2)
然后我就死刚T1,取得了12.5分的好成绩o(╥﹏╥)o。
交完T1后,打了T2的30%,其他的输出0,估分30+100=130,结果(大众分200+)
在这里插入图片描述
Surprising!
其实T1我就打错了2个地方:一个k<=m-mid打成k<m-mid,跑SAP之前无脑加了个dis[S]=1(尘封多年的SAP居然没有打错!)
T2是数位DP,题解写得很好,这里贴上来:

我们可以注意到,若一个串为回文串,必有以下两个条件中至少一个成立:
1:有两个相邻的数字相等。
2:有两个相隔一个数字的数字相等。
所以我们可以用状态f(i, p, q),表示在 1~i 位,第 i 个数字为 q,第 i-1 个数字为 p 的合法方案数,进行数位 DP。保证以上两个条件均不成立即可。时间复杂度 O ( log ⁡ 2 max ⁡ ( a , b ) × 1 0 3 ) O(\log_2\max(a,b)\times 10^3) O(log2max(a,b)×103)。(不要被这么小的 a,b 迷惑了~)
进行数位 DP 的一般方法
设 x 表示除了数位 i 以外的状态,本题是 p,q。若求区间[l,r]之间的答案,我们用[0,r]的答案减去[0,l-1]的答案。下文“原串”表示这里的 r 或者 l-1。我们就是要保证 DP 到的状态都小于等于原串。
方法 1
顺推,设状态 f(i,x,k),k=0(表示 1~i-1 位都和原串一样)或 1(有至少一位小于原串)。枚举第 i 位数字 c,若 k=0,则 c≤原串第 i 位,否则 c≤9,若 i 为数字的开头则保证 c>0。按情况转移即可。
方法 2
先逆推,设状态 f(i,x),表示 i 位数符合情况的所有答案,不必考虑和原串的关系。注意逆推时 x 的定义可能稍有变化,比如本题 p,q 不再表示最右侧数字而表示最左侧。然后顺序扫描一遍,同理枚举 c<原串第 i 位,然后对于所有 1~i-1位与原串相同,第 i 位为 c 的答案都包含在 f(n-i,x)中。统计求和即可。

然而细节却多得可怕!
我改了一个晚上,无果,于是用苏DL的方法,改了一个早上,亦无果,谁知下午一到机房就发现自己哪里错了!原来是数组没有初始化。。。
这题递推的话很显然要分开做[0…l-1]和[0…r]。
我本来是设 f i , x , y , 0 / 1 , 0 / 1 f_{i,x,y,0/1,0/1} fi,x,y,0/1,0/1表示当前做了1~ i 位,其中第 i − 2 i-2 i2 ~ i i i位是 x y ‾ \overline{xy} xy的非回文数字数,而第一个0/1表示是否等于上限,第二个0/1表示是否有前缀0。
结果出现了一堆重复状态……
苏DL的方法是设 f i , x , y , z f_{i,x,y,z} fi,x,y,z表示当前做了1~ i 位,其中第 i − 2 i-2 i2 ~ i i i位是 x y z ‾ \overline{xyz} xyz的非回文数字数。
这样子要先处理i=1,2,3的情况,码量有点大。
我真应该用记忆化搜索的

T3可以证明以下情况中答案=0:

  1. N<M
  2. 环数大于1
  3. 有偶环

于是只剩下树和1个奇环的情况了。
第一种情况就是我的水分方法,第二种情况先把环外面的处理掉,再解方程就好了。

总结:算法还是要及时复习啊!有些“难题”要勤于思考!


CODE

牛棚安排

#include<cstdio>
#include<cstring>
using namespace std;
#define N 1005
#define M 25
#define S 0
int a[1025][1025],cow[N][M],shed[M],dis[1025],GAP[1025],T;
char ch;
inline char gc()
{
    
    
	static char buf[500000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &k)
{
    
    
	while(ch=gc(),ch<'0'||ch>'9');k=ch-'0';
	while(ch=gc(),ch>='0'&&ch<='9') k=k*10+ch-'0';
}
int dfs(int k,int flow)
{
    
    
	if(k==T) return flow;
	int i,have=flow,now;
	for(i=0;i<=T;i++)
	{
    
    
		if(a[k][i]&&dis[k]==dis[i]+1)
		{
    
    
			now=dfs(i,have<a[k][i]?have:a[k][i]);
			a[k][i]-=now,a[i][k]+=now,have-=now;
			if(!have) return flow;
		}
	}
	if((--GAP[dis[k]])==0) dis[S]=T;
	++GAP[++dis[k]];
	return flow-have;
}
int main()
{
    
    
	int n,m,i,j,k,l,r,mid,sum,ans=-1;
	read(n),read(m),T=n+m+1;
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			read(cow[i][j]);
	for(i=1;i<=m;i++) read(shed[i]);
	l=1,r=m;
	while(l<=r)
	{
    
    
		mid=l+r>>1;
		for(k=0;k<=m-mid;k++)
		{
    
    
			memset(a,0,sizeof(a));
			memset(GAP,0,sizeof(GAP));
			memset(dis,0,sizeof(dis));
			for(i=1;i<=n;i++)
			{
    
    
				a[S][i]=1;
				for(j=1;j<=mid;j++)
					a[i][n+cow[i][k+j]]=1;
			}
			for(i=1;i<=m;i++) a[n+i][T]=shed[i];
			for(sum=0;dis[S]<T;sum+=dfs(S,0x7fffffff));
			if(sum==n) break;
		}
		if(k<=m-mid) r=mid-1,ans=mid;
		else l=mid+1;
	}
	printf("%d\n",ans);
	return 0;
}

非回文数字

#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define N 19
ll f[N][10][10][10],a[N],ten[N];
bool b[N];
inline ll solve(ll n)
{
    
    
	if(n<=10) return n+1;
	ll i,j,x,y,z,len=0,ans=0;
	memset(f,0,sizeof(f));
	memset(b,0,sizeof(b));
	for(i=n;i;a[++len]=i%10,i/=10);
	for(i=len>>1;i>0;i--) j=a[i],a[i]=a[len-i+1],a[len-i+1]=j;
	b[1]=1;
	for(i=2;i<=len;i++)
	{
    
    
		if(a[i]!=a[i-1]&&(i==2||a[i]!=a[i-2])) b[i]=1;
		else break;
	}
	for(i=0;i<=9;i++) f[len][0][0][i]++;
	if(len>1)
		for(i=1;i<=9;i++)
			for(x=0;x<=9;x++)
				if(i!=x)
					if(len==2)
					{
    
    
						if(i*10+x<a[1]*10+a[2]) f[2][0][i][x]++;
					}
					else f[len][0][i][x]++;
	if(len>2)
		for(i=1;i<=9;i++)
			for(x=0;x<=9;x++)
				if(i!=x)
					for(y=0;y<=9;y++)
						if(x!=y&&y!=i)
						{
    
    
							if(i*100+x*10+y<a[1]*100+a[2]*10+a[3]) f[3][i][x][y]++;
							for(j=4;j<=len;j++) f[j][i][x][y]++;
						}
	for(i=3;i<len;i++)
	{
    
    
		for(x=0;x<=9;x++)
			for(y=0;y<=9;y++)
				for(z=0;z<=9;z++)
					if(f[i][x][y][z])
						for(j=0;j<=9;j++)
							if(y!=z&&y!=j&&z!=j)
								f[i+1][y][z][j]+=f[i][x][y][z];
		if(b[i]) for(j=0;j<a[i+1];j++)
		{
    
    
			if(a[i-1]!=j&&a[i]!=j)
				f[i+1][a[i-1]][a[i]][j]++;
		}
	}
	for(i=0;i<=9;i++)
		for(x=0;x<=9;x++)
			for(y=0;y<=9;y++)
				ans+=f[len][i][x][y];
	if(b[len]) ans++;
	return ans;
}
int main()
{
    
    
	ll n,m;ten[0]=1;
	for(n=1;n<19;n++) ten[n]=ten[n-1]*10;
	scanf("%lld%lld",&n,&m);
	printf("%lld\n",solve(m)-solve(n-1));
	return 0;
}

管道

猜你喜欢

转载自blog.csdn.net/huangzihaoal/article/details/94623536
今日推荐