给定 a a a与 b b b,输出 a × b a×b a×b。
直接模拟即可。
#include
#define int long long
using namespace std;
int a,b;
signed main()
{
cin>>a>>b;
cout<<a*b<<endl;
return 0;
}
给定 n n n个数,请求出它们的乘积。特别的,如果该值大于 1 0 18 10^{18} 1018则输出 − 1 -1 −1。
显然,由题意可以写出这个式子:
if (tot*a[i]>1000000000000000000) return cout<<-1<<endl,0;
注意,这里的 t o t ∗ a i tot*a_i tot∗ai会溢出!既然乘法不行,就用除法呗~
if (tot>1000000000000000000/a[i]) return cout<<-1<<endl,0;
注意,这两个式子可以互相转换的,依据是不等式的基本性质。
还有一件重要的事情——在判断溢出前,看一下给定的那些数中是否有 0 0 0,如果有就直接输出 0 0 0并结束程序。
#include
#define int long long
#define inf 1000000000000000000
using namespace std;
int n,tot=1,a[200005];
signed main()
{
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i];
for (int i=1;i<=n;i++)
{
if (a[i]==0) return cout<<0<<endl,0;
}
for (int i=1;i<=n;i++)
{
if (tot>inf/a[i]) return cout<<-1<<endl,0;
tot*=a[i];
}
cout<<tot<<endl;
return 0;
}
不会做……
尽可能多地把 n n n拆分为多个不同的,且是某个质数的正整数次方数 的数的乘积,并输出最多的个数。
做法显然。先质因数分解,即 n = ∏ i = 1 k a i b i n=∏_{i=1}^k a_i^{b_i} n=∏i=1kaibi。
可以得到,对于每对 ( a i , b i ) (a_i,b_i) (ai,bi),我们需要将 b i b_i bi拆分为 1 + 2 + 3 + … … + x + y 1+2+3+……+x+y 1+2+3+……+x+y,并且要拆分得尽可能地多;所以,假设最多可以拆分为 n o w now now个,那么答案就是 ∑ n o w \sum now ∑now。
注意质因数分解的时间复杂度需要限制在 O ( n ) O(\sqrt n) O(n)以内,如果不会可以看我的另外一篇博客——质因数分解详解。
#include
#define int long long
using namespace std;
int n,ans=0;
signed main()
{
cin>>n;
if (n==1) return cout<<0<<endl,0;
for (int i=2;i*i<=n;i++)
{
if (n%i==0)
{
int pos=0;
while (n%i==0) n=n/i,pos++;
int now=sqrt(pos*2);
if (now*(now+1)>pos*2) now--;
ans+=now;
}
}
if (n>1) ans++;
cout<<ans<<endl;
return 0;
}
给定 n n n对 l i l_i li与 r i r_i ri,且数组 a a a满足 l i ≤ a i ≤ r i ( 1 ≤ i ≤ n ) l_i≤a_i≤r_i(1≤i≤n) li≤ai≤ri(1≤i≤n)。现在,请求出数组 a a a有多少种不同的中位数。
显然,我们要分奇偶类讨论。
① n n n为奇数。
容易发现,此时中位数仅仅与 a a a数组中最中间的那个数 x x x有关。于是,我们将 l l l数组与 r r r数组按升序排序,那么有 l m i d ≤ x ≤ r m i d ( m i d = ( n + 1 ) / 2 ) l_{mid}≤x≤r_{mid}(mid=(n+1)/2) lmid≤x≤rmid(mid=(n+1)/2)。所以,此时中位数有 r m i d − l m i d + 1 r_{mid}-l_{mid}+1 rmid−lmid+1种。
② n n n为偶数。
容易发现,此时中位数与 a a a数组中最中间的那两个数 x , y x,y x,y有关;只要 x + y x+y x+y的值不同,那么中位数就不同(中位数为 x + y 2 \frac {x+y} 2 2x+y)。于是,我们将 l l l数组与 r r r数组按升序排序,那么有 l l m i d + r l m i d ≤ x + y ≤ l r m i d + r r m i d l_{lmid}+r_{lmid}≤x+y≤l_{rmid}+r_{rmid} llmid+rlmid≤x+y≤lrmid+rrmid,其中 ( l m i d = n / 2 , r m i d = l m i d + 1 ) (lmid=n/2,rmid=lmid+1) (lmid=n/2,rmid=lmid+1)。所以,此时中位数有 l r m i d + r r m i d − l l m i d − r l m i d + 1 l_{rmid}+r_{rmid}-l_{lmid}-r_{lmid}+1 lrmid+rrmid−llmid−rlmid+1种。
时间复杂度: O ( n ) O(n) O(n)。
显然不可能做到这么优秀。
排序时间复杂度: O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
总时间复杂度: O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
#include
#define int long long
using namespace std;
int n,ans;
int a[200005],b[200005];
signed main()
{
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i]>>b[i];
sort(a+1,a+n+1);
sort(b+1,b+n+1);
if (n%2==0) ans=b[n/2]+b[(n/2)+1]-a[n/2]-a[(n/2)+1]+1;
else ans=b[(n+1)/2]-a[(n+1)/2]+1;
cout<<ans<<endl;
return 0;
}
给定集合 a a a(暂且当 a a a中数可以重复),请问存在多少个不同的 a a a的子集使得子集中存在子集的和为 s s s?
由于答案可能过大,请将其对 998244353 998244353 998244353取模。
显然,如果集合 a a a的某个大小为 k k k的子集 S S S满足要求,那么它对答案的贡献就是 2 n − k 2^{n-k} 2n−k。
然后设计状态,其中 d p i dp_i dpi表示所有数和为 i i i的子集对答案的贡献之和。
接着,考虑状态转移。如果某个和为 s u m 1 sum_1 sum1的子集大小为 k k k,添加了一个数 a i a_i ai后成为了一个和为 s u m 1 + a i sum_1+a_i sum1+ai且大小为 k + 1 k+1 k+1的子集,贡献也除以了2(贡献从 2 n − k 2^{n-k} 2n−k变成了 2 n − k − 1 2^{n-k-1} 2n−k−1)。
所以,状态转移就是: d p j + = d p [ j − a i ] / 2 dp_j+=dp[j-a_i]/2 dpj+=dp[j−ai]/2。
但是,状态转移涉及到除法与取模,所以除以2要用逆元。
时间复杂度: O ( n 2 ) O(n^2) O(n2)。
#include
#define int long long
using namespace std;
const int mod=998244353;
int n,s;
int a[3005],dp[3005];
int quick_power(int x,int y)
{
int res=1;
for (;y;y=y>>1,x=(x*x)%mod)
{
if (y&1) res=(res*x)%mod;
}
return res;
}
signed main()
{
cin>>n>>s;
for (int i=1;i<=n;i++) cin>>a[i];
dp[0]=quick_power(2,n);
for (int i=1;i<=n;i++)
{
for (int j=s;j>=a[i];j--) dp[j]=(dp[j]+(dp[j-a[i]]*499122177)%mod)%mod;
}
cout<<dp[s]<<endl;
return 0;
}
排名没进前3500,太惨了,赛后诸葛亮……
①A题切掉;
②B题WA了10次才AC,罚时50分钟;甚至有几次提交了同样的WA代码;心态崩溃;
④D题切掉;
⑤E题看都没看,直接搞B题去了……比赛后看到E题才发现如此简单;
⑥F题快速幂板子打错,且忘记逆元,不知道在搞啥QWQ
最终死得非常惨,大家不要学我这个菜鸡啊~
我艹%&@*