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

题目

【集训队互测2013】家族

Description

阿狸和桃子养了n 个小阿狸, 小阿狸们每天都在一起玩的很开心. 作为工程师的阿狸在对小阿狸们之间的关系进行研究以后发现了小阿狸的人际关系由某种神奇的相互作用决定, 阿狸称之为“键”. 每个键有一个频率, 称为键频率, 是一个整数(单位Hz)。
由于小阿狸们每天成集团地黏在一起, 桃子希望他们能够分成更加独立的几团. 阿狸发现, 一旦小阿狸们分开, 独立的一块连在一起的几个小阿狸就会形成一个家族, 而家族的类型由这个家族的小阿狸的数量唯一确定(比如说只有一个小阿狸的家族显然就是单身码农, 两个小阿狸的显然是一对小阿狸恋人, 三个小阿狸的就是三口之家等等)显然, 一个小阿狸和另一个小阿狸处于同一家族,当且仅当两个小阿狸之间存在直接或间接的键组成的路径。
桃子对每种小阿狸家族都有自己的喜好程度, 她希望所有的小阿狸家族喜好程度之和大于等于K。
为了让小阿狸们分开来, 阿狸决定让某些键断裂, 只保留某一段频率的键,比如说100Hz 到140Hz 频率的键, 这时频段宽度为40Hz. 当然, 阿狸希望频段宽度越小越好, 但至少要有一个小键. 你的任务就是求出最小的频段宽度.
注意, 输入不保证全部键都有效时只有一个小阿狸家族。

Input

第一行3 个整数n(<=1000), m(<=5000), K(0~2^31-1)。
接下来1 行n 个整数, 第i 个整数表示桃子对大小为i 的小阿狸家族的喜爱程度。
接下来m 行, 每行3 个整数, u, v, f. 表示u 小阿狸和小阿狸v 之间存键, 频率f Hz。

Output

一个整数, 即最窄的频段宽度(不存在可行频段, 输出"T_T", 不含引号).

Sample Input

输入1:
4 4 52
1 50 2 9
1 2 6
2 3 8
3 4 4
1 4 3
输入2:
4 4 10
1 5 2 9
1 2 6
2 3 8
3 4 4
1 4 3
输入3:
4 4 10
1 4 2 9
1 2 6
2 3 8
3 4 4
1 4 3

Sample Output

输出1:
0
样例解释1:频段3Hz~3Hz 或4Hz~4Hz 或6Hz~6Hz 或8Hz~8Hz

输出2:
2
样例解释2:频段4Hz~6Hz

输出3:
T_T

Data Constraint

对于30% 的数据, n <=10
对于50% 的数据, n <=50 , m <=200
对于100% 的数据, n <=1000 , m <=5000,频率f Hz<100000。


【集训队互测2013】供电网络

Description

阿狸和桃子居住的世界里, 只有一个国家, 这个国家有很多城市, 每个城市直接由中央政府管辖.
电力是这个国家的唯一能源, 但是每个城市的发电能力都不一样, 于是就产生了某些城市电力不足, 而某些城市却电力过剩的情况.
阿狸作为国家的首席工程师, 阿狸的一项重要工作就是均衡整个国家的电力, 使得每个城市的电力都恰好没有剩余或不足.
好在一些城市之间有电线可以输送电力, 这些电线都有自己的输送上限和下限, 并且输送电力的同时会产生大量的热.
每条电线i 发出的热量一定是关于输送电量的一个没有常数项的二次函数,即a_ix^2+b_ix, 并且由于电线是二极管做成的, 很显然只能单向输送电力. 每单位热量需要用1 单位的金币来冷却. 任何两个城市之间, 至多有一条电线.
不幸的是, 有时电力网络不像我们想的那么完美, 某些情况下可能无论如何都不能满足整个国家的电力需求. 这种情况下就只好向别的世界购买电力或者将电力输出给别的世界(注意, 每个城市的电力不能有剩余!), 每个城市买入或者输出电力的价格是不一样的(输出也要花钱).
由于阿狸的国家没有小数的概念, 输送,、购买或者交换电力都必须是以整数1 为单位.
阿狸的任务是最小化金币的花费(买入/送出的费用+电线上发热的冷却费用),他最近被这个问题搞得焦头烂额, 以至于没有时间去陪桃子玩, 结果天天被桃子骂T_T. 好在有你, 万能的程序猿, 请你编写一个程序来帮阿狸解决这个问题吧.

Input

第一行2 个整数, n 和m, 分别是城市个数和有向电线条数.
接下来n 行, 每行3 个整数[left, in, out], 其中第k 行表示第k 个城市的信息:
left 表示这个城市剩余(负数为不足)的电量, -5 <= left <= 5.
in, out 表示这个城市买入或送出一个单位电量的价格. 0 <= in, out <= 10000
最后m 行, 每行6 个整数, u, v, a, b, L, U 其中第k 行表示第k 条电线的信息:
u, v 分别表示电线的开始和结束城市(电力只能从u 输送到v).
a, b 表示电线发热的二次函数的二次项和一次项.
L, U 表示电线输送电力的下界和上界.

Output

仅一个整数, 表示最小的金币花费.

Sample Input

3 2
1 1 1
-2 20 0
-4 20 0
1 2 1 0 0 10
2 3 0 3 0 10

Sample Output

53
样例解释:
城市1买入5个单位电力, 花费5.
城市1输出6个单位电力到城市2, 花费36.
城市3输出4个单位电力到城市3, 花费12.
总花费53

Data Constraint

对于5%的数据满足m = 0.
对于30%的数据满足n <= 30, L = 0, a = 0.
对于60%的数据满足n <= 50, m <= 200.
对于100%的数据满足n <= 200, m <= 600, u != v, 1 <= u, v <= n, 1 <= a, b <=3, 1 <= L <= 10, 1 <= L <= U <= 100, 0 <= in, out <= 100, -5 <= left <= 5.


【集训队互测2013】城市规划

Description

刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.
刚才说过, 阿狸的国家有n 个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通.
为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案.
好了, 这就是困扰阿狸的问题. 换句话说, 你需要求出n 个点的简单(无重边无自环)无向连通图数目.
由于这个数字可能非常大, 你只需要输出方案数mod 1004535809(479 * 2 ^21 + 1)即可.

Input

仅一行一个整数n(<=130000)

Output

仅一行一个整数, 为方案数mod 1004535809.

Sample Input

输入1:
3
输入2:
4
输入3:
100000

Sample Output

输出1:
4
输出2:
38
输出3:
829847355

Data Constraint

对于20%的数据, n <= 10
对于40%的数据, n <= 1000
对于60%的数据, n <= 30000
对于80%的数据, n <= 60000
对于100%的数据, n <= 130000


总结

今天我实际上只做了1个小时的比赛,10:30以前都在改昨天的非回文数字了(居然还没有调出来!)
尽管如此,分数还是不低
在这里插入图片描述
T1是一眼题,可以先把边按频率排序,很明显我们要选一段连续的边。
看见m那么小,就想到暴力枚举区间的起点和终点,一条一条边加进并查集,动态维护答案就可以了。
T2好复杂!正想放弃,看到了一行话:

对于5%的数据满足m = 0.

m=0,直接花钱导进\导出电就可以了。
T3打表,11:29:58点击OK,结果OJ太卡,然后就GG
A few seconds later…
咦?T1怎么了?
奈何XC没开题,只好调昨天的非回文数字了。

下午来到机房,题目已经开了,我点开数据一看:

10 20 85
9 10 12 32 30 24 56 24 0 70
2 10 2675764
8 10 2045851
6 8 1310539
6 9 3281109

等等,说好的“频率f Hz<100000”呢?
在这里插入图片描述
于是前所未有地快速AC。
T2是上下界费用流,由于不会费用流,放弃。
T3:
f n f_{n} fn表示n个城市组成简单无向连通图的答案。
那么我们可以用总方案数 2 C n 2 2^{C_n^2} 2Cn2减去不合法状态,而不合法的状态就是把n塞进一个集合里(也可以不塞),大小为 i 的集合(不计n)有 C n − 1 i − 1 C_{n-1}^{i-1} Cn1i1个,这个集合内部的方案是 f i f_i fi,其他点的排列方案数为 2 C n − i 2 2^{C_{n-i}^2} 2Cni2,整理一下,列出状态转移方程: f n = 2 C ⁡ n 2 − ∑ i = 1 n − 1 C ⁡ n − 1 i − 1 × f i × 2 C ⁡ n − i 2 f_n=2^{\operatorname{C}_n^2}-\sum_{i=1}^{n-1}\operatorname{C}_{n-1}^{i-1}\times f_i\times 2^{\operatorname{C}_{n-i}^2} fn=2Cn2i=1n1Cn1i1×fi×2Cni2
两边同时减去 f n f_n fn并移项,得
2 C ⁡ n 2 = ∑ i = 1 n C ⁡ n − 1 i − 1 × f i × 2 C ⁡ n − i 2 2^{\operatorname{C}_n^2}=\sum_{i=1}^n\operatorname{C}_{n-1}^{i-1}\times f_i\times 2^{\operatorname{C}_{n-i}^2} 2Cn2=i=1nCn1i1×fi×2Cni2
拆开组合数,得
2 C ⁡ n 2 = ∑ i = 1 n ( n − 1 ) ! ( i − 1 ) ! ( n − i ) ! × f i × 2 C ⁡ n − i 2 2^{\operatorname{C}_n^2}=\sum_{i=1}^n\frac{(n-1)!}{(i-1)!(n-i)!}\times f_i\times 2^{\operatorname{C}_{n-i}^2} 2Cn2=i=1n(i1)!(ni)!(n1)!×fi×2Cni2
两边同时除以 ( n − 1 ) ! (n-1)! (n1)!,得
2 C ⁡ n 2 ( n − 1 ) ! = ∑ i = 1 n f i ( i − 1 ) ! × 2 C ⁡ n − i 2 ( n − i ) ! \frac{2^{\operatorname{C}_n^2}}{(n-1)!}=\sum_{i=1}^n\frac{f_i}{(i-1)!}\times \frac{2^{\operatorname{C}_{n-i}^2}}{(n-i)!} (n1)!2Cn2=i=1n(i1)!fi×(ni)!2Cni2
那么令 A = ∑ i = 1 n f i ( i − 1 ) ! A=\sum_{i=1}^n\frac{f_i}{(i-1)!} A=i=1n(i1)!fi B = ∑ i = 1 n 2 C ⁡ i 2 ( i − 1 ) ! B=\sum_{i=1}^n\frac{2^{\operatorname{C}_{i}^2}}{(i-1)!} B=i=1n(i1)!2Ci2 C = ∑ i = 0 n 2 C ⁡ i 2 i ! C=\sum_{i=0}^n\frac{2^{\operatorname{C}_{i}^2}}{i!} C=i=0ni!2Ci2
原式就变成了 A × C = B A\times C=B A×C=B由于我们要求的是 f ,所以要求出A,移项,得 A = B × C − 1 A=B\times C^{-1} A=B×C1
这就变成了多项式求逆的问题了。
若现有多项式 A ( x ) , B ( x ) A(x),B(x) A(x),B(x),B的度小于等于A的度,已知A,求B,且A,B满足 A × B ≡ 1 ( m o d &ThinSpace;&ThinSpace; x n ) A\times B\equiv1\quad(\mod x^n) A×B1(modxn)
显然 A × B ≡ 1 ( m o d &ThinSpace;&ThinSpace; x ⌊ n 2 ⌋ ) A\times B\equiv1\quad(\mod x^{\left\lfloor \frac{n}{2}\right\rfloor}) A×B1(modx2n)
A × B ′ ≡ 1 ( m o d &ThinSpace;&ThinSpace; x ⌊ n 2 ⌋ ) A\times B&#x27;\equiv1\quad(\mod x^{\left\lfloor \frac{n}{2}\right\rfloor}) A×B1(modx2n)
两式相减,得 A ( B − B ′ ) ≡ 0 ( m o d &ThinSpace;&ThinSpace; x ⌊ n 2 ⌋ ) A(B-B&#x27;)\equiv 0\quad(\mod x^{\left\lfloor \frac{n}{2}\right\rfloor}) A(BB)0(modx2n)
除以A(A一定不为0,因为当A=0时,B不存在) B − B ′ ≡ 0 ( m o d &ThinSpace;&ThinSpace; x ⌊ n 2 ⌋ ) B-B&#x27;\equiv 0\quad(\mod x^{\left\lfloor \frac{n}{2}\right\rfloor}) BB0(modx2n)
平方 B 2 + B ′ 2 − 2 B × B ′ ≡ 0 ( m o d &ThinSpace;&ThinSpace; x n ) B^2+B&#x27;^2-2B\times B&#x27;\equiv 0\quad(\mod x^n) B2+B22B×B0(modxn)
乘上A B + A B ′ 2 − 2 B ′ ≡ 0 ( m o d &ThinSpace;&ThinSpace; x n ) B+AB&#x27;^2-2B&#x27;\equiv 0\quad(\mod x^n) B+AB22B0(modxn)
于是 B ≡ 2 B ′ − A B ′ ( m o d &ThinSpace;&ThinSpace; x n ) B\equiv 2B&#x27;-AB&#x27;\quad(\mod x^n) B2BAB(modxn)
因此可以递归求解。
递归边界?当n=1时,若 A = ∑ i = 0 m a i x i A=\sum_{i=0}^{m}a_ix^i A=i=0maixi,则 A ≡ a 0 , B = a 0 − 1 ( m o d &ThinSpace;&ThinSpace; x ) A\equiv a_0,B=a_0^{-1}\quad(\mod x) Aa0,B=a01(modx)
时间复杂度 O ( n log ⁡ 2 n ) O(n\log_2n) O(nlog2n)
实现过程麻烦,建议封装NTT。
P.S:我本来打算学的是分治FFT O ( n log ⁡ 2 2 n ) O(n\log_2^2n) O(nlog22n))的,结果学错了,不过没关系,多项式求逆更快。


CODE

T1

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1005
#define M 5005
struct edge
{
    
    
	ll start,end,lenth;
}a[M];
bool cmp(edge x,edge y){
    
    return x.lenth<y.lenth;}
ll f[N],size[N],num[N];
inline ll getfather(ll k)
{
    
    
	if(f[k]==k) return k;
	return f[k]=getfather(f[k]);
}
int main()
{
    
    
	ll n,m,k,i,j,x,y,z,sum,ans=0x7fffffff;
	scanf("%lld%lld%lld",&n,&m,&k);
	for(i=1;i<=n;i++)
	{
    
    
		scanf("%lld",num+i);
		if(num[i]>k) num[i]=k;
	}
	for(i=1;i<=m;i++)
	{
    
    
		scanf("%lld%lld%lld",&x,&y,&z);
		a[i]=(edge){
    
    x,y,z};
	}
	sort(a+1,a+m+1,cmp);
	for(i=1;i<=m;i++)
	{
    
    
		sum=num[1]*n;
		for(j=1;j<=n;j++) f[j]=j,size[j]=1;
		for(j=i;j<=m;j++)
		{
    
    
			x=a[j].start,y=a[j].end;
			if(getfather(x)!=getfather(y))
			{
    
    
				sum-=num[size[f[x]]]+num[size[f[y]]];
				size[f[y]]+=size[f[x]],f[f[x]]=f[y];
				sum+=num[size[f[y]]];
			}
			if(sum>=k)
			{
    
    
				if(a[j].lenth-a[i].lenth<ans) ans=a[j].lenth-a[i].lenth;
				break;
			}
		}
	}
	if(ans<0x7fffffff) printf("%lld\n",ans);
	else puts("T_T");
	return 0;
}

T3

#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define swap(a,b) temp=a,a=b,b=temp
#define P 1004535809
#define N 300005
#define g 3
ll A[N],B[N],C[N],c[N],fac[N],inv[N],rev[N],num,temp,x;
inline ll pow(ll x,ll y=P-2)
{
    
    
    ll s=1;
    while(y)
    {
    
    
        if(y&1) s=s*x%P;
        x=x*x%P,y>>=1;
    }
    return s;
}
inline void ntt(ll *a,ll maxn,bool inv)
{
    
    
    ll i,j,mid;
    for(i=0;i<maxn;i++)
        if(i<rev[i])
            swap(a[i],a[rev[i]]);
    for(mid=1;mid<maxn;mid<<=1)
    {
    
    
        num=pow(g,(P-1)/(mid<<1));
        if(inv) num=pow(num);
        for(i=0;i<maxn;i+=mid<<1)
        {
    
    
            temp=1;
            for(j=0;j<mid;j++,temp=temp*num%P)
            {
    
    
                x=temp*a[i+j+mid]%P;
                a[i+j+mid]=(a[i+j]+P-x)%P,a[i+j]=(a[i+j]+x)%P;
            }
        }
    }
    if(inv)
    {
    
    
        j=pow(maxn);
        for(i=0;i<maxn;i++) a[i]=a[i]*j%P;
    }
}
inline void work(ll *a,ll *b,ll deg)
{
    
    
    if(deg==1){
    
    b[0]=pow(a[0],P-2);return;}
    work(a,b,deg+1>>1);
    ll i,j,maxn;
    for(maxn=1,j=-1;maxn<=(deg<<1);maxn<<=1,j++);
    for(i=1;i<maxn;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<j);
    memset(c,0,sizeof(c));
    for(i=0;i<deg;i++) c[i]=a[i];
    ntt(c,maxn,0),ntt(b,maxn,0);
    for(i=0;i<maxn;i++) b[i]=(2-c[i]*b[i]%P+P)%P*b[i]%P;
    ntt(b,maxn,1);
    for(i=deg;i<maxn;i++) b[i]=0;
}
int main()
{
    
    
	ll n,i,j,m;
	scanf("%lld",&n),fac[0]=inv[0]=1;
	for(i=1;i<=n;i++) fac[i]=fac[i-1]*i%P,inv[i]=pow(fac[i]);
	for(i=1;i<=n;i++)
	{
    
    
		j=pow(2,i*i-i>>1);
		C[i]=j*inv[i]%P;
		B[i]=j*inv[i-1]%P;
	}
    for(m=1,j=-1;m<=(n<<1);m<<=1,j++);
	C[0]=1,work(C,A,n+1);
	for(i=1;i<m;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<j);
	ntt(A,m,0),ntt(B,m,0);
	for(i=0;i<m;i++) A[i]=A[i]*B[i]%P;
	ntt(A,m,1);
	printf("%lld\n",A[n]*fac[n-1]%P);
	return 0;
}

猜你喜欢

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