A.大整数分解
题目:
思路:A ^B最快的方法是先求出A的所有质因子, 然后用类似快速幂的方法增加到B次方,因为每个质因子都是独立增加的,假设它的质因子为p1 ^c1, p2 ^c2,p3 ^c3…,如果此时p1、p2、p3这三个因子都算出来了并且都乘上了,而它们的次方c又大于1的话,我们只要同时乘以 p1 * p2 * p3,它们是独立增长的 ,所以只需要知道最大的c就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1000100, M=1000000;
int prime[N], st[N], cnt;
void init(){
for(int i=2; i<=M; i++)
{
if(!st[i]) prime[++cnt]=i;
for(int j=1; prime[j]<=M/i; j++)
{
st[prime[j]*i]=1;
if(i%prime[j]==0) break;
}
}
}
int main(){
int A, B;
init();
cin>>A>>B;
int maxn=0, res1=0;
for(int i=1; i<=cnt; i++)
{
int x=0;
while(A%prime[i]==0 && A>0)
{
x++;
A/=prime[i];
}
if(x)
{
res1++;
maxn=max(x, maxn);
}
}
maxn*=B;
cout<<res1+(int)ceil(log2(maxn));
return 0;
}
E.规律游走
题目:
思路:找规律的题, 每4ab走的路线是一样的。具体实现用数字来表示四个方向,j=0为右, j=1为上,j=2为左, j=3为下。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PII pair<int, ll>
#define x first
#define y second
int main(){
int n, a, b;
cin>>n>>a>>b;
int len=4*a*b;
vector<PII> pace(len+1);
for(int i=1; i<len+1; i++)
{
int j=((i-1)/a-(i-1)/b)%4;//看一下此时是a的几倍,是b的几倍,也就是表示向左转90°转了几次,向右转90°转了几次
if(j<0) j+=4;//如果是负数,那么就是向右转的次数多于向左转的次数,相当j是正数的逆过程
pace[i]=pace[i-1];
if(j==0) pace[i].x++;
else if(j==1) pace[i].y++;
else if(j==2) pace[i].x--;
else pace[i].y--;
}
cout<<pace[n%len].x+pace[len].x*(n/len)<<" "<<pace[n%len].y+pace[len].y*(n/len);//一共走了多少次这样的循环
return 0;
}
I.巧克力棒
题目:
思路:题目要求等差数列的数量,2 1 3、3 2 1 这样的等差数列和1 2 3是一样的,因此考虑排序。排完序后,由于等差数列的公差是一样的,一个合法的等差数列加上现在符合这个公差的数就能长度加一,设dp[i][j]为选了第i个数,公差为j的等差数列的数量,由于j的范围很大,开一个map来存,dp[i][ a[i]-a[j] ]=dp[i][ a[i]-a[j] ]+dp[j][ a[i]-a[j] ],最后加上n,也就是长度为1的等差数列。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2100, mod=998244353;
map<int, ll> dp[maxn];
int a[maxn];
int main(){
int n;
cin>>n;
for(int i=1; i<=n; i++) cin>>a[i];
sort(a+1, a+n+1);
for(int i=1; i<=n; i++)//初始化长度为2的等差数列
{
for(int j=1; j<i; j++)
{
dp[i][a[i]-a[j]]++;
}
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<i; j++)
{
dp[i][a[i]-a[j]]=(dp[i][a[i]-a[j]]+dp[j][a[i]-a[j]])%mod;
}
}
ll ans=0;
for(int i=1; i<=n; i++)
{
for(auto &j: dp[i])
{
ans=(ans+j.second)%mod;
}
}
cout<<(ans+n)%mod;
return 0;
}
I.归零
题目:
思路:可以进行的操作是对相邻点进行+1或者-1,假设输入数组是一个差分数组,还原出任意一个合法的原数组,这个+1或者-1操作就是对于原数组的一个数进行+1或者-1,答案要求出最小操作次数,也就是使还原出的的这个原数组的每一个数都变成同一个数,让我们求出原数组的每一个数减去这个数的和最小,这里有一个中位数的性质,给定一个数列,所有数与中位数的绝对差之和最小,所以只要求出原数组的每个数减去中位数之和。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=510;
ll a[N], b[N];
int main(){
int n;
cin>>n;
for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
for(int i=2; i<=n; i++) b[i]=b[i-1]+a[i];
sort(b+1, b+n+1);
ll ans=0;
ll x=b[(n+1)/2];
for(int i=1; i<=n; i++) ans+=abs(b[i]-x);
cout<<ans;
return 0;
}