• SSZX集训 Contest 20210203 递推,最小生成树,矩阵快速幂,染色


    题目已存档至百度网盘

    前言: 还行,就是有人AK,令人不爽


    方阵(matrix)

    标程是记录每行每列的染色时间,我的做法是从指令最后往前处理,染色过的就不能再染了.时间复杂度为 O ( n + n m + q ) O(n+nm+q) O(n+nm+q),可以通过.

    /*
    从后往前排,排过的就锁住不能再排了
    
    问题:1、快写居然出问题了 
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXQ=1e6+5,MAXN=1e3+5;
    int n,m,q,x[MAXQ],y[MAXQ],z[MAXQ],tot;
    bool vish[MAXN],visl[MAXN],vis_map[MAXN][MAXN];
    int ans[MAXN][MAXN];
    
    inline int read()
    {
    	int s=1,x=0;char c=getchar();
    	while(c>'9'||c<'0'){if(c=='-')s=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
    	return s*x;
    }
    
    //void write(int x)
    //{
    //	if(x<0)
    //	{
    //		x=-x;
    //		putchar('-');
    //	}
    //	else if(x>9)
    //	{
    //		write(x/10);
    //	}
    //	putchar();
    //}
    
    int main()
    {
    	freopen("matrix.in","r",stdin);
    	freopen("matrix.out","w",stdout);
    	
    	n=read();
    	m=read();
    	q=read();
    	const int tot_map=n*m;
    	
    	for(int i=1;i<=q;i++)
    	{
    		x[i]=read();y[i]=read();z[i]=read();
    	}
    	for(int i=q;i>=1;i--)
    	{
    		int h=y[i];
    		if(x[i]==1&&vish[h]==false)
    		{
    			for(int j=1;j<=m;j++)
    			{
    				if(vis_map[h][j]==false)
    				{
    					ans[h][j]=z[i];
    					vis_map[h][j]=true;
    					tot++;
    				}
    			}
    			vish[h]=true;
    		}
    		if(x[i]==2&&visl[h]==false)
    		{
    			for(int j=1;j<=n;j++)
    			{
    				if(vis_map[j][h]==false)
    				{
    					ans[j][h]=z[i];
    					vis_map[j][h]=true;
    					tot++;
    				}
    			}
    			visl[h]=true;
    		}
    		if(tot==tot_map)
    			break;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			printf("%d",ans[i][j]);
    			putchar(' ');
    		}
    		putchar('
    ');
    	}
    	
    	return 0;
    }
    

    另外,此题的write函数居然出锅了,应该这么写:

    void write(int x)
    {
    	if(x<0)
    	{
    		x=-x;
    		putchar('-');
    	}
    	else if(x>9)
    	{
    		write(x/10);
    	}
    	putchar(x%10+48);
    }
    

    putchar(x%10+48)不是putchar(`x%10+48`)

    坐标系(coordinate)

    此题为Openjudge那道奶牛散步数据加强版,递推经典题呀.递推关系式为 f n = 2 f n − 1 + f n − 2 f_n=2f_{n-1}+f_{n-2} fn=2fn1+fn2.但今天做的时候显然忘记了,于是先搞了一个dfs把前几项算了出来.又因为前几天在接受数学的熏陶,弄了很久的差分表,结果发现根本弄不出来,直接吐血.(其实显然弄不出来,因为答案并不能被表示为多项式)

    但好就好在,偶从差分表中看出了规律,最后列出了递推关系式.

    另外,这道题数据范围过大,考虑优化.

    方案一: 打表

    在本机测试了用时:

    1000000000
    999999966
    Use Time:16.217000
    

    也就是说,我们将复杂度优化到 1 0 7 10^7 107即可.

    我 们 已 经 知 道 了 f n = 2 f n − 1 + f n − 2 , 那 么 显 然 , 要 知 道 f n , 只 用 知 道 f n − 1 和 f n − 2 . 选 择 打 出 所 有 f n 与 f n + 1 ( n = 1 0 7 k , k 为 正 整 数 ) 我们已经知道了f_n=2f_{n-1}+f_{n-2},那么显然,要知道f_n,只用知道f_{n-1}和f_{n-2}.选择打出所有f_n与f_{n+1}(n=10^7k,k为正整数) fn=2fn1+fn2,,fn,fn1fn2.fnfn+1(n=107k,k)

    具体操作如下代码,也是考试时写出来的.打表的数据是用原本的未优化代码生成的.

    #include <bits/stdc++.h>
    #define ll long long
    
    using namespace std;
    ll n;
    ll biao1[1005]={0,627935421,438953224,542068249,329814112,560895073,119554882,817838024,413683704,457693522,548686427,625090930,854797397,507897869,61876493,38377219,305397032,834552550,86754567,509991039,595114395,406847212,670491536,432878314,135680620,898309326,728242939,198112061,177816349,19047210,455754392,852650532,521176598,71125034,245305647,837039919,188113267,56598060,432474979,432717386,87865010,771920945,438742654,288408342,246724129,896686551,339943192,339062029,917394372,746339567,880572807,739796257,59753287,776287897,225152152,836502060,948930900,475746791,722277745,851272656,790561977,985377610,885700761,132420780,835281543,520522277,705708011,107967744,357214655,287632826,452485219,234406704,490642737,105936544,662318372,10700633,44184524,425184700,853280967,501062760,425337376,984713729,821083793,448257541,299730624,956477347,53544543,258784453,686484973,12946211,133711137,828167667,821810848,728440912,992782964,810060630,81297710,592494925,333385653,68086064,999999966};
    ll biao2[1005]={0,316019740,372654023,224763656,22469312,782122008,34120220,931864090,425814224,323613731,426904732,655133268,419960676,600143856,636422754,404303050,514440356,364914981,228761950,38777592,133257557,122058434,66188449,284201981,606451036,708146069,58038914,491958600,718356299,472529774,855728576,454092882,3075198,128033925,672313652,274523182,685346016,965382417,79327031,70919624,314176084,524093558,507000754,423517629,401454042,306672104,839594331,294033500,29439574,960708835,59713600,296223267,981986607,148291544,877858011,326733601,500718454,694404815,412489057,164309652,746610433,220032885,261585106,940108177,802956593,46695727,852179533,782419693,57729179,975765453,190151629,400743276,947414172,856017108,746680441,337348962,303616399,286766519,671925310,423986587,856516568,213870031,317318877,493679984,182995823,98269674,305866735,16514990,809398153,525848172,231896493,533455685,956438514,294996456,409710864,32400151,771974784,207954764,741176549,835969528};
    
    int main()
    {
    //	freopen("coordinate.in","r",stdin);
    //	freopen("coordinate.out","w",stdout);
    	
    	register long long f[3]={3,7};
    	register long long mod=1e9+7;
    	cin>>n;
    	if(n<=2)
    	{
    		cout<<f[n-1]<<endl;
    		return 0;
    	}
    	
    	if(n<=10000000)
    	{
    		for(register int i=3;i<=n;i++)
    		{
    			f[2]=(2*f[1]+f[0])%mod;
    			f[0]=f[1],f[1]=f[2];
    		}
    		cout<<f[2]<<endl;
    	}
    	else
    	{
    		int k=n/10000000;
    		n%=10000000;
    		f[0]=biao1[k];
    		f[1]=biao2[k];
    		if(n<=1)
    		{
    			cout<<f[n]<<endl;
    			return 0;
    		}
    		for(register int i=2;i<=n;i++)
    		{
    			f[2]=(2*f[1]+f[0])%mod;
    			f[0]=f[1],f[1]=f[2];
    		}
    		cout<<f[2]<<endl;
    	}
    	
    	
    	return 0;
    }
    

    方案二: 矩阵快速幂

    递推关系式的优化都可以用到矩阵快速幂,前几天讲课时也提到过,我已经写了一篇新的博客来介绍.

  • 相关阅读:
    第九周作业
    第八周
    第七周
    Jmeter连接到Mysql
    数据库常用链接URL写法
    功能测试方法
    常建输入框的测试
    系统业务流程测试(转)
    Linux
    搭建Git服务器
  • 原文地址:https://www.cnblogs.com/huaruoji/p/14425563.html
Copyright © 2020-2023  润新知