高一高考集訓歡樂賽

wlesq發表於2024-06-12

image
注意細節

點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 200000+5;
int n,m,a[N],b[N],c1,c2;char s[N];
int main()
{
	speed();
	freopen("grade.in","r",stdin);
	freopen("grade.out","w",stdout);
	cin>>n>>m;
	cin>>s+1;
	bool flag=0;
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='.')
		{
			flag=1;
			continue;
		}
		if(flag)b[++c2]=s[i]-'0';
		else a[++c1]=s[i]-'0';
	}
	int wei=c2;
	for(int i=1;i<=c2;i++)
	{
		if(b[i]>=5)
		{
			for(int j=i;j>=1;j--)
			{
				if(b[j]>=5)
				{
					wei=j-1;
					b[wei]++;
					m--;		
					if(!m)break;
				}
			}
			break;	//	一定不能忘	
		}

	}
	if(b[0])//進位
	{
		flag=0;
		int tmp=c1;
		a[tmp]++;
		while(a[tmp]>=10)
		{
			a[tmp]-=10;
			a[tmp-1]++;
			tmp--;
		}
	}
	if(a[0])cout<<a[0];//進位
	for(int i=1;i<=c1;i++)cout<<a[i];
	if(flag)
	{
		cout<<".";
		for(int i=1;i<=wei;i++)cout<<b[i];
	}
	return 0; 
}

image
codeforces
從一道紫題變為了黃題
我們其實只需要確定IP地址前兩部分,因為迴文,IP地址後兩部分可以確定,注意IP地址長度大於4小於12,然後就是搜尋了,還要注意每個數都至少出現過一次
遍歷前三部分比較方便,而且複雜度可以接受,所以就是\(O(255^3)\)

點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 15;
int n,acc[N],used[N],tot;
vector <int> num,Ans[10005];
bool check(int x)
{
	if(!x)return 1;
	used[x%10]++;
	return check(x/10)&&acc[x%10];
}
bool huiwen(int a,int b,int c,int d)
{
	int len=num.size()-1;
//	if(len>11)return 0;
	for(int i=0;i<=len;i++)
	{
		if(num[i]!=num[len-i])return 0;
	}++tot;
	Ans[tot].pb(a);Ans[tot].pb(256);Ans[tot].pb(b);Ans[tot].pb(256);
	Ans[tot].pb(c);Ans[tot].pb(256);Ans[tot].pb(d);
//	for(int i=0;i<=len;i++)cout<<num[i]<<" ";
//	cout<<endl;
	return 1;
}
void del(int x)
{
	if(!x)return;
	used[x%10]--;
	del(x/10);
}
void pushup(int x)
{
	if(!x)return;
	pushup(x/10);
	num.pb(x%10);
}
bool hf()
{
	for(int i=0;i<=9;i++)
	{
//		cout<<i<<" "<<used[i]<<" "<<acc[i]<<endl;
		if(!used[i]&&acc[i])
		{
			return 0;
		}
	}
	return 1;
}
int start(int a,int b,int c)
{
	num.clear();
	int tmp=0;
	pushup(a/10);num.pb(a%10);
	pushup(b/10);num.pb(b%10);
	pushup(c/10);num.pb(c%10);
//	cout<<a<<" "<<b<<" "<<c<<endl;

//	for(auto v:num)cout<<v<<" ";
//	cout<<endl;
	int flag=0;
	flag=1;
	num.pb(num[0]);//最後一部分是一位數
	tmp+=huiwen(a,b,c,num[0]);
	if(num[1])//最後一部分是兩位數
	{
		if(flag==1)num.pop_back();
		num.pb(num[1]);
		num.pb(num[0]);
		tmp+=huiwen(a,b,c,10*num[1]+num[0]);
		flag=2;
	}
	if(num[1]*10+num[2]*100+num[0]<=255&&num[2])//最後一部分是三位數
	{
		if(flag==2)
		{
			num.pop_back();
			num.pop_back();			
		}else if(flag==1)
		{
			num.pop_back();
		}
		num.pb(num[2]);
		num.pb(num[1]);
		num.pb(num[0]);
		tmp+=huiwen(a,b,c,num[1]*10+num[2]*100+num[0]);
	}
//	int sb;
//	{
//		cout<<"%%"<<a<<" "<<b<<" "<<c<<endl;
//		cout<<tmp<<" "<<"AC"<<endl;
//		cin>>sb;
//	}
	return tmp;
}

int main()
{
	speed();
//	freopen("ipadd.in","r",stdin);
//	freopen("ipadd.out","w",stdout);
	cin>>n;
	int a;
	for(int i=1;i<=n;i++)//IP length>=4 <=12
	{
		cin>>a;
		acc[a]=1;
	}
	ll ans=0;
	for(int i=0;i<=255;i++)
	{
		used[i%10]++;//一定要考慮0的情況
		if(check(i/10)&&acc[i%10])
		{
			for(int j=0;j<=255;j++)
			{
				used[j%10]++;
				if(check(j/10)&&acc[j%10])
				{
					for(int k=0;k<=255;k++)
					{
						used[k%10]++;
						if(check(k/10)&&acc[k%10]&&hf())
						{
							ans+=start(i,j,k);
						}
						used[k%10]--;
						del(k/10);
					}
				}
				used[j%10]--;
				del(j/10);
			}			
		}
		used[i%10]--;//回溯
		del(i/10);
	}
	cout<<ans<<endl;
	for(int i=1;i<=tot;i++)//輸出方案
	{
		for(auto v:Ans[i])
		{
			if(v==256) cout<<".";
			else cout<<v;
		}
		cout<<endl;
	}
	return 0; 
}

C. 裝飾

image
水題,找規律即可

點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 200000+5;
int T;
int main()
{
	speed();
	freopen("decorate.in","r",stdin);
	freopen("decorate.out","w",stdout);
	cin>>T;
	ll a,b,c;
	while(T--)
	{
		cin>>a>>b>>c;
		
		if((a+b+c)==max({a,b,c}))
		{
			cout<<0<<endl;
		}else
		{
			priority_queue <ll> q;
			q.push(a);q.push(b);q.push(c);
			a=q.top();q.pop();b=q.top();q.pop();c=q.top();
			ll ans=0;
			ans=min((b+c),(a+b+c)/3);
			cout<<ans<<endl;
		}
	}
	return 0; 
}
/*
5
1 2 3
5 0 0
9 1 1
5 5 4
0 6 6
*/

D. 最大子矩陣Largest Submatrix

image

炸裂的暴力

點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int mod=1e9+7;
ll n,m,ans,dp[1005][1005],a[1005][1005];char g[1005][1005],tmp[1005][1005];

int get(int i,int j)
{
	if(g[i][j]=='a')return 1;//0001
	if(g[i][j]=='b')return 2;//0010
	if(g[i][j]=='c')return 4;//0100
	if(g[i][j]=='w')return 3;//0011
	if(g[i][j]=='y')return 5;//0101
	if(g[i][j]=='z')return 7;//0111
	if(g[i][j]=='x')return 6;//0110
}
int main()
{					//w a,b
					//x b,c
					//y a,c
					//z a,b,c
	speed();
	freopen("matrix.in","r",stdin);
	freopen("matrix.out","w",stdout);
	while(cin>>m>>n)
	{
		ans=0;
		for(int i=1;i<=m;i++)//w y z //w x z//x y z
		{
			cin>>g[i]+1;
		}
		for(int i=1;i<=m;i++)//w y z //w x z//x y z
		{
			for(int j=1;j<=n;j++)
			{
				a[i][j]=get(i,j);
			}
		}ans=0;
		for(int i=1;i<=m;i++)		
		{
			for(int j=1;j<=n;j++)
			{
				int now=1;
				for(int ii=i;ii<=m;ii++)		
				{
					for(int jj=j;jj<=n;jj++)
					{
						now=a[ii][jj];
						for(int iii=i;iii<=ii;iii++)		
						{
							for(int jjj=j;jjj<=jj;jjj++)
							{
								now&=a[iii][jjj];
								if(!now)break;
							}
							if(!now)break;
						}
						if(now)ans=max<ll>(ans,abs(ii-i+1)*(jj-j+1));
					}
					
				}
				
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

現在想正解,我們可以貪心一下,遍歷三次,每一次,把能變為a/b/c的都變為相同的a/b/c,這樣再找最大的
如何找呢,可以用類似玉蟾宮的思想,先處理出每一列列相同元素的長,然後用棧維護,注意j-stk.top()-1這樣就不用從左往右,從右往左搜兩遍了
image

點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int mod=1e9+7;
ll n,m,ans,dp[1005][1005];char g[1005][1005],tmp[1005][1005];
void find(char tg)
{
//	cout<<"&&&&"<<endl;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=n;j++)
		{
//			cout<<tmp[i][j];	
			dp[i][j]=0;
			if(tmp[i][j]==tg)dp[i][j]=dp[i-1][j]+1;
		}
//		cout<<endl;
	}
	stack <int> stk;
	for(int i=1;i<=m;i++)
	{
 		for(int j=0;j<=n+1;j++)
 		{
 			while(!stk.empty()&&dp[i][j]<dp[i][stk.top()])
 			{
 				int tmp=dp[i][stk.top()];//一定是最小的
 				stk.pop();
 				if(stk.empty())break;
// 				cout<<stk.top()<<endl;
 				ans=max<ll>(ans,tmp*(j-stk.top()-1));
// 				cout<<ans<<endl;
// 				stk.pop();
			}
			stk.push(j);
		}
	}
}
int main()
{					//w a,b
					//x b,c
					//y a,c
					//z a,b,c
	speed();
	freopen("matrix.in","r",stdin);
	freopen("matrix.out","w",stdout);
	while(cin>>m>>n)
	{
		ans=0;
		memset(g,0,sizeof g);
		for(int i=1;i<=m;i++)//w y z //w x z//x y z
		{
			cin>>g[i]+1;
		}
		for(int p=1;p<=3;p++)
		{
			for(int x=1;x<=m;x++)
			{
				for(int y=1;y<=n;y++)
				{
					if(p==1&&(g[x][y]=='w'||g[x][y]=='y'||g[x][y]=='z'))
					{
						tmp[x][y]='a'-1+p;
					}
					else if(p==2&&(g[x][y]=='w'||g[x][y]=='x'||g[x][y]=='z'))
					{
						tmp[x][y]='a'-1+p;
					}
					else if(p==3&&(g[x][y]=='x'||g[x][y]=='y'||g[x][y]=='z'))
					{
						tmp[x][y]='a'-1+p;
					}else
					{
						tmp[x][y]=g[x][y];
					}
				}
			}	
			find('a'-1+p);		
		}
		cout<<ans<<endl;
//		cout<<"%%%%%%%%%"<<endl;
	}
	return 0;
}

E. 中國象棋

image

設計\(dp[i][j][k]\)有j列有1個炮,有k列有2個炮
image

點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 105,mod=9999973;
ll n,m;ll dp[N][N][N];
ll calc(ll x)
{
	return 1ll*x*(x-1)%mod/2%mod;
}
int main()
{
	speed();
	freopen("chess.in","r",stdin);
	freopen("chess.out","w",stdout);
	cin>>n>>m;
//	for(int i=0;i<=m;i++)dp[0][i][m-i]=1;
	dp[0][0][0]=1;
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=m;j++)
		{
			for(int k=0;k<=m-j;k++)
			{
				dp[i][j][k]=dp[i-1][j][k]%mod;
				if(k>=1)dp[i][j][k]+=dp[i-1][j+1][k-1]*(j+1)%mod;
				if(k>=2)dp[i][j][k]+=dp[i-1][j+2][k-2]%mod*((j+2)*(j+1)/2)%mod;
				if(j>=1)dp[i][j][k]+=dp[i-1][j-1][k]*(m-k-j+1)%mod;
				if(j>=2)dp[i][j][k]+=dp[i-1][j-2][k]*calc(m-k-j+2)%mod;
				if(k>=1)dp[i][j][k]+=dp[i-1][j][k-1]%mod*(m-j-k+1)%mod*j%mod;
				dp[i][j][k]%=mod;
//				cout<<i<<" "<<j<<" "<<k<<" "<<dp[i][j][k]<<endl;
//				ans+=dp[i][j][k];
			}
		}
	}
//	ll ans=0;
	for(int j=0;j<=m;j++)
		for(int k=0;k<=m;k++)//這裡注意一下不是m-j
			ans=(ans+dp[n][j][k])%mod;
	cout<<ans<<endl;
	return 0; 
}

F. 奇妙的 Fibonacci

image

這題還是比較有思想的
首先證明\(F_i|F_j,則i|j\)
證明:\(F_i=f_{i-1}*f_2+f_{i-2}*f_1\)
\(F_i=f_{i-3}*f_2+f_{i-2}*f_3\)
同理:\(F_i=f_{i-k}*f_{k-1}+f_{i-k+1}*f_k\)
不停帶入\(k\),可推廣出\(f_{n+m}-f_{n-1}\times f_m+f_n \times f_{m+1}\)
顯然\(f_i與f_{i-1}\)互質
類比\(gcd(n+m,m)=gcd(n,m)\)
\(gcd(f_{n+m},f_m)=gcd(f_n,f_m)\)
也就是說,對於相同的\(n,m\),上述兩個同時成立\(f_i|f_j,i|j\)

\(A_i\)\(i\)的約數個數,\(B_i\)\(i\)的約數平方和,\(C_i\)\(i\)的最小質因數的冪是多少,\(D_i\)\(i\)除去所有最小質因子後剩下的數
\(A_i\),\(B_i\)滿足互質積性
\(設q為質因子\)
\(A_q=2,B_q=1+q^2,C_q=1,D_q=1\)
\(gcd(i,q)=1,A_{iq}=A_i*A_q,B_{iq}=B_i*B_q,C_{iq}=1,D_{iq}=i\)
\(i|q,A_{iq}=A_i/(C_i+1)*(C_i+2),B_{iq}=B_i*q^2+B_{D_i},C_{iq}=C_i+1,D_{iq}=D_i\)

注意\(f_2\)是所有\(f_i\)的約數,要特判

點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define mk make_pair 
#define pb push_back
#define lid (rt<<1)
#define rid (rt<<1|1)
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int N = 1e7+5,MAX = 1e7,mod=1e9+7;
ll A[N],B[N],C[N],D[N],pr[N],tot,n,q[N],c;bool vis[N];
void get()
{
	A[1]=1;B[1]=1;
	for(int i=2;i<=MAX;i++)
	{
//		cout<<i<<endl;
		if(!vis[i])
		{
			pr[++tot]=i;
			A[i]=2;
			B[i]=(1ll*i*i%mod+1)%mod;//(i*i是int必須加longlong)
			C[i]=1;
			D[i]=1;
		}
		for(int j=1;j<=tot;j++)
		{
//			cout<<j<<endl;
			ll num=pr[j]*i;
			if(num>MAX)break;
			vis[num]=1;
			if(i%pr[j]==0)//pr[j]是i的最小質因子 
			{	
				A[num]=A[i]/(C[i]+1)*(C[i]+2);
				C[num]=C[i]+1;D[num]=D[i];
				B[num]=(B[i]*1ll*(pr[j]%mod*pr[j])%mod+B[D[i]]%mod)%mod;
				
				
				break;
			}
			else//pr[j]變成了i*pr[j]的最小質因子 ,因為i的最小質因子還沒有遍歷到 
			{
				C[num]=1;
				B[num]=(B[i]*(pr[j]%mod*pr[j])%mod+B[i]%mod)%mod;
				//B[num]=B[i]*B[pr[j]]%mod;
				A[num]=A[i]*A[pr[j]]%mod;
				D[num]=i;				
				
			}

		}
	}
}
int main()
{
	speed();
	freopen("fibo.in","r",stdin);
	freopen("fibo.out","w",stdout);
	cin>>n;
	get();
	
	ll Q1,a,b;
	cin>>Q1>>a>>b>>c;
	
	q[1]=Q1;
	for(int i=2;i<=n;i++)
	{
		q[i]=(q[i-1]*a%c+b%c)%c+1;
//		cout<<q[i]<<endl;
	}
	ll A1=0,A2=0;
	for(int i=1;i<=n;i++)
	{
		A1+=A[q[i]]+(q[i]&1);
		A2=(A2+B[q[i]]+4*(q[i]&1))%mod;
		A1%=mod;A2%=mod;	
	}
	cout<<A1<<endl<<A2<<endl;
	return 0;
}

相關文章