CSP-S 前的比賽記錄


ABC222

rk1865,手速太慢了。

A和B都是語法題。

C是個小模擬,過 m 輪每一輪 2k-1 名和 2k 名比較誰贏了計入進去,每一輪弄完之后直接在排序啊。

#include <bits/stdc++.h>
using namespace std;
const int N=1010;
 
//by zplqwq
inline int read()
{
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
int n,m;
struct node 
{
	string s;
	int pos,qwq;
	friend bool operator<(const node& a, const node& b) 
	{
		if(a.qwq!=b.qwq) return a.qwq>b.qwq;
		return a.pos<b.pos;
	} 
}a[N];
int check(char a, char b) 
{
	if(a==b) return 0;
	if(a =='G' and  b=='C' or a=='C' and b =='P' or a=='P' and b=='G') return 1;
	return -1;
}
 
int main() 
{
	n=read();
	m=read();
	for(int i=1;i<=2*n;i++) 
	{
		cin>>a[i].s;
		a[i].pos=i;
		a[i].qwq=0;
	}
	for(int i=0;i<m;i++)
	{
		sort(a+1,a+1+2*n);
		for(int j=1;j<=n;j++)
		{
			char tmp=a[2*j-1].s[i];
			char tmpp=a[2*j].s[i];
			if(check(tmp,tmpp)>0)a[2*j-1].qwq++;
			else if(check(tmp,tmpp)<0) a[2*j].qwq++;
		}
	}
	sort(a+1,a+1+2*n);
	for(int i=1;i<=2*n;i++)cout<<a[i].pos<<endl;
	return 0;
}

D 是個 dp.

考慮 \(dp_{i,j}\) 表示總共\(i\) 個數字結尾為 \(j\) 的方案數。

得到轉移方程:

\[dp_{i,j}=\left\{\begin{array}{l}f_{0,0}=1\\ f_{i,j}=\sum{0\le k\le j} f_{i-1,k} (i \ge 1 & a_i \le j \le b_i)\\ \end{array}\right. \]

但顯然這個轉移方程不夠優。

因此我們考慮前綴和優化。

\(s_{i,j}\) 表示 \(dp_{i,j}\) 的前綴和。

\(sum_{i,j}=(sum_{i,j-1}+dp_{i,j})\)

然后 \(dp_{i,j}=sum_{i-1,j}\) 然后就做完了。

答案即為所有 \(dp_{n,i}\) 的和。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read()
{
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
// by : zplqwq
const int N=5010;
int n,k;
const int mod=998244353;
int dp[N][N];
int ans=0;
int a[N];
int b[N];
int sum[N][N];
signed main()
{
	n=read();
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	dp[0][0]=1;
	for(int i=0;i<=3000;i++)
	{
		sum[0][i]=1;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=a[i];j<=b[i];j++)
		{
			dp[i][j]=sum[i-1][j];
		}
		for(int j=0;j<=3000;j++)
		{
			sum[i][j]=(sum[i][j-1]+dp[i][j])%mod;
		}
	}
	int ans=0;
	for(int i=0;i<=3000;i++)
	{
		ans+=dp[n][i]; 
		ans%=mod;
	}
	cout<<ans<<endl;
	return 0;
}

EFGH 不會,決定這個上午搞定 E 和 F。

草 突然發現 G 是大水題。

這個 idea 確實一看就不新,但我也確實沒做過,這回算是知道了,以后再遇到就會做了。

藍書上,AcWing,POJ 都有收錄。

首先 \(x\)\(2\) 連在一起組成的正整數可寫作 \(\frac{2\times (10^x-1)}{9}\) 題目就是讓我們求一個最小的 \(x\) 滿足,\(k | \frac{2\times (10^x-1)}{9}\)

\(d=\gcd(k,2)\)

那么 \(k|\frac{2\times (10^x-1)}{9} \iff 9\times k | 2 \times ( 10^x-1) \iff \frac{9 \times k}{d}| 10^x-1 \iff 10^x \equiv 1 (\mod \frac{9 \times k}{d})\)

得到一個引理

若正整數 \(a,n\) 互質,則滿足 \(a^x \equiv 1 (\mod n)\) 的最小正整數 \(x_0\)\(\phi(n)\) 的約數。

具體證明可以參考藍書。

因此我們只需求出歐拉函數 \(\phi(\frac{9 \times k}{d})\) 枚舉他的所有約數,用快速冪逐一檢查是否滿足條件即可。

時間復雜度 \(O(\sqrt{k} \log k)\) 可過。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read()
{
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
ll qsm(ll x,ll n,ll mod) 
{
  ll ret=1;
  while(n) 
  {
    if(n&1) ret=ret*x%mod;
    n>>=1;
    x=x*x%mod;
  }
  return ret;
}

ll phi(ll n)
{
	int ans=n;
	for(int i=2;i<=sqrt(n);i++)
	{
		if(n%i==0)
		{
			ans=ans/i*(i-1);
			while(n%i==0) n/=i;
		}
	}
	if(n>1) ans=ans/n*(n-1);
	return ans;
}
int main()
{
	int T;
	ll k;
	T=read();
	while(T--)
	{
		k=read();
		ll d=__gcd(k,2ll);
		ll n=phi(9ll*k/d);
		ll ret=1e18;
		for(ll i=1;i*i<=n;i++)
		{
			if(n%i!=0) continue;
			if(qsm(10,i,9ll*k/d)==1) 
			{
				ret=min(ret,i);
			}
			if(qsm(10,n/i,9ll*k/d)==1)
			{
				ret=min(ret,n/i);
			}
		}
		if(ret==1e18) cout<<-1<<endl;
		else cout<<ret<<endl;
	}
	return 0;
}

晚上CF前20min切掉了E。

背包裸題,感覺不難想。

首先可以記錄一下那條按照那條路徑遍歷整棵樹之后每條路徑被遍歷了多少次。

設為 \(c_1,c_2,..c_{n-1}\),那么答案就轉換為把這個數組分成兩個部分使得其中一個部分減去另一個部分為 \(k\)

然后再變一下。

\(S=c_1+c_2+...+c_{n-1}\) 然后題目就又變成了,有多少種方案在 \(c\) 數組里選擇使得和為 \(\frac{k+s}{2}\)

然后就可以 \(dp\) 了。

\(dp_{i,j}\) 表示 \(c_1...c_i\) 中選一些數是的和是 \(j\) 的總方案數。

考慮 \(01\) 背包。

做完了。

#include <bits/stdc++.h>
using namespace std;
const int N=2000010;
const int mod=998244353;
inline int read()
{
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
int n,m,k,s;
int a[N];
int head[N];
int c[N];
int dp[N];
int cnt=0;
struct Edge
{
    int to,nextt,id;
}e[N];
void add(int u,int v,int w)
{
	e[++cnt].to=v;
	e[cnt].nextt=head[u];
	e[cnt].id=w;
	head[u]=cnt;
}
bool dfs(int cur,int want,int fa)
{
	if(cur==want) return 1;
	for(int i=head[cur];i;i=e[i].nextt)
	{
		int tmp=e[i].to;
		int id=e[i].id;
		if(tmp!=fa)
		{
			if(dfs(tmp,want,cur))
			{
				c[id]++;
			//	cout<<c[id]<<endl;
				return 1;
			}
		}
	}
	return 0;
 } 
 
int main()
{
    n=read();
	m=read();
	k=read();
	for(int i=1;i<=m;i++)
	{
		a[i]=read();
	}
	for(int i=1;i<n;i++)
	{
		int u,v;
		u=read();
		v=read();
		add(u,v,i);
		add(v,u,i);
	}
 
	for(int i=1;i<=m-1;i++)
	{
		dfs(a[i],a[i+1],0);
	
	}
    dp[0]=1;
    for(int i=1;i<n;i++)
    {
        s+=c[i];
        for(int j=s;j>=c[i];j--)
        {
        	(dp[j]+=dp[j-c[i]])%=mod;
        //	cout<<j<<" "<<dp[j]<<endl;
		}
    } 
    if((s+k)%2==1 or s+k<0)
    {
    	cout<<0<<"\n";
	}
	else cout<<dp[(k+s)/2]<<"\n";
    return 0;
}

打了場CF,切ABCD。

明天來補吧。

CF A:只要有一列都是1就不行。

CF B:硬剛模擬吧

CF C:枚舉其中一個數,計算出另一個數的值,判斷是否存在。

CF D:小學奧數,用總情況減去不滿足題意的情況即可。

我現在看啥都想 dp ()

A:

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
char a[N];
char b[N];
int n;
int flag;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n;
		cin>>a;
		cin>>b;
		for(int i=0;i<n;i++)
		{
			if(a[i]=='1' and b[i]=='1')
			{
				cout<<"NO"<<endl;
				flag=1;
				break;
			} 
		}
		if(flag==0)	cout<<"YES"<<enB:dl;
		flag=0;
	}
	return 0;
}

B:

#include <bits/stdc++.h>
using namespace std;
const int N=1010;
 
int T;
int n;
int a[N][N];
int cnt[N];
 
int main()
{
	cin>>T;
	while(T--)
	{
		cin>>n;
		for(int i=1;i<=5;i++)
		{
			cnt[i]=0;
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=5;j++)
			{
				cin>>a[i][j];
				if(a[i][j]==1)
				{
					cnt[j]++;
				}
			}
		}
		int flag=0;
		for(int i=1;i<=5;i++)
		{
			for(int j=1;j<=5;j++)
			{
				if(i!=j)
				{
					int tmp=1;
					int aa=0;
					int b=0;
					int c=0;
					for(int k=1;k<=n;k++)
					{
						if(!a[k][i] and !a[k][j]) 
						{
							tmp=0; 
							break;
						}
						if(a[k][i] and a[k][j]) c++;
						else if(a[k][i]) aa++;
						else b++;
					}
					if(tmp and aa+c>=n/2 and b+c>=n/2) 
					{
						flag=1; 
						break;
					}
				}
			}
		}
		if(flag==1)
		{
			cout<<"YES"<<endl;
		}
		else
		{
			cout<<"NO"<<endl;
		}
	}
	return 0;
}

C:

#include <bits/stdc++.h>
using namespace std;
inline double DoubleRead()
{
    long long s = 0, w = 1, k = 0, n = 0, m = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') w = -1;
        ch = getchar();
    }
    while((ch >= '0' && ch <= '9') || ch == '.')
    {
        
        if (ch == '.')
            n = 1;
        else if (n == 0)
            s = s * 10 + ch - '0';
           else k = k * 10 + ch - '0', m++;
        ch = getchar();
    }
    return (pow(0.1, m) * k + s) * w;
}
inline int read()
{
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
#define ll long long
const ll N = 2e5+5;
 
ll T,n;
ll a[N];
map<ll,ll> mp;
int main() 
{
	cin>>T;
	while(T--)
	{
		mp.clear();
		cin>>n;
		ll sum=0;
		ll summ=0;
		ll ans=0;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			sum+=a[i];
			++mp[a[i]];
		}
		if((sum*2)% n) 
		{
			puts("0"); 
			continue;
		}
		summ=sum*2/n;
		for(int i=1;i<=n;i++)
		{
			if(summ-a[i]>a[i]) ans+=mp[summ-a[i]];
		}
		if(!(summ%2)) ans+=mp[summ/2]*(mp[summ/2]-1)/2;
		cout<<ans<<endl;
	}
	return 0;
}

D:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll N = 2e5+5;
 
ll T,n;
ll a[N],b[N];
ll cnta[N],cntb[N];
 
int main()
 {
	cin>>T;
	while(T--) 
	{
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cnta[i]=0;
			cntb[i]=0;
		}
		for(int i=1;i<=n;i++)
		{
			cin>>a[i]>>b[i];
			cnta[a[i]]++; 
			cntb[b[i]]++;
		}
		ll qwq=0;
		ll ans=n*(n-1)/2*(n-2)/3;
		for(int i=1;i<=n;i++) 
		{
			ll tmp=(cnta[a[i]]-1)*(cntb[b[i]]-1);
			qwq+=tmp;
		}
		cout<<ans-qwq<<endl;
	}
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM