UOJ Round #1 部分题解

A

不难发现是要找一个 x x x 使这个东西最小: ∑ i = 1 n a i   m o d   x + ⌊ a i x ⌋ \sum_{i=1}^n a_i \bmod x+\lfloor \dfrac {a_i} x \rfloor i=1naimodx+xai

推一推:
∑ i = 1 n a i − x × ⌊ a i x ⌋ + ⌊ a i x ⌋ = ( ∑ i = 1 n a i ) − ( x − 1 ) × ∑ i = 1 n ⌊ a i x ⌋ \begin{aligned} &\sum_{i=1}^n a_i-x\times \lfloor \frac {a_i} x \rfloor+\lfloor \frac {a_i} x \rfloor\\ &=(\sum_{i=1}^n a_i)-(x-1)\times\sum_{i=1}^n \lfloor \frac {a_i} x \rfloor \end{aligned} i=1naix×xai+xai=(i=1nai)(x1)×i=1nxai

枚举 x x x,后面那一串可以 O ( n x ) O(\dfrac n x) O(xn) 求,总时间复杂度就是 O ( n ln ⁡ n ) O(n\ln n) O(nlnn)

代码如下:

#include <cstdio>
#define maxn 1000010
#define ll long long

int n,a[maxn],b[maxn];
ll sum=0,ans=999999999999999,tot;
int min(int x,int y){
    
    return x<y?x:y;}

int main()
{
    
    
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),sum+=a[i],b[a[i]]++;
	for(int i=1;i<=maxn-10;i++)b[i]+=b[i-1];
	for(int i=1;i<=maxn-10;i++)
	{
    
    
		tot=0;
		for(int j=i;j<=maxn-10;j+=i)
		tot+=(ll)(b[min(j+i-1,maxn-10)]-b[j-1])*(j/i);
		if(tot*(1-i)<ans)ans=tot*(1-i);
	}
	printf("%lld",ans+sum);
}

B

不难发现一个性质,如果 a i < a j a_i<a_j ai<aj a i a_i ai a j a_j aj 前面,那么模了 a i a_i ai 后无论 a j a_j aj 在哪里都无所谓,因为 x x x 已经小于 a j a_j aj 了。

所以可以将所有数从大到小排个序后依次考虑,设 f i , j f_{i,j} fi,j 表示模了前 i i i 个数后值为 j j j 的方案数,考虑第 i i i 个数是否有贡献,有就直接模,令 f i , j   m o d   a i + = f i − 1 , j f_{i,j\bmod a_i}+=f_{i-1,j} fi,jmodai+=fi1,j,没有就将它放到比他小的一个 a j a_j aj 后面,方案数为 n − i n-i ni,使 f i , j + = f i − 1 , j × ( n − i ) f_{i,j}+=f_{i-1,j}\times (n-i) fi,j+=fi1,j×(ni) 即可。

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
#define ll long long
#define mod 998244353

int n,x,a[1010];
ll f[1010][5010];
bool cmp(int x,int y){
    
    return x>y;}

int main()
{
    
    
	scanf("%d %d",&n,&x);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	sort(a+1,a+n+1,cmp);
	f[0][x]=1;
	for(int i=1;i<=n;i++)
	for(int j=0;j<=x;j++)
	f[i][j%a[i]]=(f[i][j%a[i]]+f[i-1][j])%mod,
	f[i][j]=(f[i][j]+f[i-1][j]*(n-i)%mod)%mod;
	for(int i=x;i>=0;i--)
	if(f[n][i]>0){
    
    printf("%d\n%lld",i,f[n][i]);return 0;}
}

C

千辛万苦看懂了题解,然后标程就几乎把我劝退了……

硬看了一两个小时,最后还是决定跑路,以后可能会来补吧。

猜你喜欢

转载自blog.csdn.net/a_forever_dream/article/details/109527827
今日推荐