暑期MQFMATH训练营2
Multiply
题目链接
题意
\(Z=a_1!*a_2!*.....*a_n!\)
\(b_i=Z*X^i\)
\(b_i是Y!的一个因子\)
给定n,X,Y的情况下,问i最多能有多大
题解
第一时间想到的就是质因数分解,然后根据质因数的个数去计算,emm.....然后就tle了
这道题求的是i,i是X的幂次,又和Z有关,很容易看出作为多个阶乘的乘积是不能算出来的,所以分解成质因数就成了最好的方法
因为\(b_i是Y!\)的因子,所以把\(Yi\)也分解成质因子的乘积,然后答案就很明显了
对于任意\(Y_i的因子y_i,在Y中有y个,在Z中有z个,在X中有x个,那么i最大就是(y-z)/x了\)
PS:因为数据量很大,所以得用pollard_rho算法,不然会tle
AC代码
#include "bits/stdc++.h"
using namespace std;
#define int long long
#define ll long long
const int maxn=2e6+10;
const int inf=0x3f3f3f3f;
const int INF=1ll<<62;
inline int rd()
{
int a;scanf("%lld",&a);return a;
}
int t,n,a[maxn],x,y;
int c1[maxn],c2[maxn],c3[maxn];
int prime[maxn],prime2[maxn],cnt=0,s=0,vis[maxn];
ll gcd(ll a, ll b) {
return b ? gcd(b, a % b) : a;
}
ll quick_mult(ll a, ll b, ll mod) {
ll ans = 0;
while(b) {
if(b & 1) ans = (ans + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return ans;
}
ll quick_pow(ll a, ll n, ll mod) {
ll ans = 1;
while(n) {
if(n & 1) ans = quick_mult(ans, a, mod);
a = quick_mult(a, a, mod);
n >>= 1;
}
return ans;
}
bool miller_rabin(ll n) {
if(n == 2) return true;
if(n < 2 || !(n & 1)) return false;
ll s = 0, d = n - 1;
while(!(d & 1)) {
d >>= 1;
s++;
}
for(int i = 1; i <= 11; i++) {
ll a = rand() % (n - 2) + 2;
ll now = quick_pow(a, d, n), pre = now;
for(int j = 1; j <= s; j++) {
now = quick_mult(now, now, n);
if(now == 1 && pre != 1 && pre != n - 1) return false;
pre = now;
}
if(now != 1) return false;
}
return true;
}
ll pollard_rho(ll n, int c) {
ll x, y, i = 1, k = 2;
x = y = rand() % (n - 2) + 2;
for( ; ; ) {
i++;
x = (quick_mult(x, x, n) + c) % n;
ll g = gcd(y - x, n);
if(g > 1 && g < n) return g;
if(x == y) return n;
if(i == k) y = x, k <<= 1;
}
}
void find_fac(ll n, int k) {
if(n == 1) return ;
if(miller_rabin(n)) {
prime[++s]=n;
return ;
}
ll p = n;
int c = k;
while(p >= n) p = pollard_rho(p, c--);
find_fac(p, k);
find_fac(n / p, k);
}
void init(){
prime2[++cnt]=prime[1];
c3[cnt]=1;
for(int i=2;i<=s;i++){
if(prime[i]==prime[i-1])c3[cnt]++;
else prime2[++cnt]=prime[i],c3[cnt]=1;
}
}
ll cal(ll n,ll x){
ll ans=0;
while(n){
ans+=n/x;
n/=x;
}
return ans;
}
signed main(){
srand((unsigned)time(NULL));
t=rd();
while(t--){
s=0;cnt=0;
n=rd();x=rd();y=rd();
find_fac(x,1111);
sort(prime+1,prime+1+s);
init();
for(int i=1;i<=n;i++){
a[i]=rd();
}
ll ans=4e18;
for(int i=1;i<=cnt;i++){
ll num=0;
for(int j=1;j<=n;j++){
num+=cal(a[j],prime2[i]);
}
ll t=cal(y,prime2[i])-num;
if(t<0)t=0;
ans=min(ans,t/c3[i]);
}
printf("%lld\n",ans);
for(int i=1;i<=cnt;i++)c3[i]=0;
}
return 0;
}
A - Simple Math 2
题目链接
题意
求给定N,M的情况下\(\lfloor\frac{10^N}{M}\rfloor\)%M的值
题解
\(\lfloor\frac{10^N}{M}\rfloor\)%M
\(=>\lfloor\frac{10^N}{M}-k*M\rfloor\)%M
\(=>\lfloor\frac{10^N-k*M^2}{M}\rfloor\)%M
\(=>\lfloor\frac{10^NmodM^2}{M}\rfloor\)%M
\(10^NmodM^2可以直接用ksm求\)
AC代码
#include "bits/stdc++.h"
using namespace std;
#define int long long
#define ll long long
const int maxn=2e6+10;
const int inf=0x3f3f3f3f;
const int INF=1ll<<62;
const int mod=1e9+7;
inline int rd()
{
int a;scanf("%lld",&a);return a;
}
int n,m;
int ksm(int a,int b=mod-2,int m=mod){
int res=1;
while(b){
if(b&1){
res*=a;
res%=m;
}
a*=a;
a%=m;
b>>=1;
}
return res;
}
signed main(){
n=rd();m=rd();
cout<<ksm(10,n,m*m)/m%m<<endl;
return 0;
}
Problem J. Prime Game
题目链接
题意
\(设 mul(l,r)=\prod_{i=l}^ra_i和fac(l,r)=mul(l,r)不同素因子的数量\)
给一个数组a,求\(\sum_{i=1}^n\sum_{j=i}^nfac(i,j)\)
题解
计算出来每个数的质因子在各个区间的贡献。
以第二个例子为例,第一个元素6的素因子2在[1,1][1,2],.....,[1,10]10个区间有贡献,所以总和加10
第一个元素6的素因子3在[1,1][1,2],.....,[1,10]10个区间有贡献,所以总和加10
而像第五个元素中素因子5的计算就需要去掉前面的5已经贡献的区间
所以第二个样例总的\(sum = 10+10+9*2+8*3+7+6*4+5*5+4+0+2*4+1+3=134\)
所以通项式\(sum_i=(n-prime[i][pos]+1)*(prime[i][pos]-prime[i][pos-1])\)
AC代码
#include "bits/stdc++.h"
using namespace std;
//#define int long long
#define ll long long
const int maxn=1e6+10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
inline int rd()
{
int a;scanf("%d",&a);return a;
}
int n,m;
int vis[maxn],prime[maxn],s=0;
vector<ll>ve[maxn];//这里没开ll,wa7
void init(){
for(int i=2;i*i<=1000010;i++) {
if(!vis[i]){
vis[i]=i;prime[++s]=i;
}
for(int j=1;j<=s;j++){
if(vis[i]<prime[j]||prime[j]*i>1010)break;
vis[prime[j]*i]=prime[j];
}
}
}
void js(int n,int pos){
int tmp=n;
for(int i=1;i<=s&&prime[i]<=n;i++){
if(tmp%prime[i]==0) {
ve[prime[i]].push_back(pos);
}
while(tmp%prime[i]==0)tmp/=prime[i];
}
if(tmp!=1){
if(!ve[tmp].size()){
prime[++s]=tmp;
}
ve[tmp].push_back(pos);
}
}
signed main(){
init();
n=rd();
for(int i=1;i<=n;i++){
int aa=rd();js(aa,i);
}
ll ans=0;
for(int i=1;i<=s;i++){
for(int j=0;j<ve[prime[i]].size();j++){
if(j!=0)ans+=(n-ve[prime[i]][j]+1)*(ve[prime[i]][j]-ve[prime[i]][j-1]);
else ans+=(n-ve[prime[i]][j]+1)*(ve[prime[i]][j]);
}
}
printf("%lld\n",ans);
return 0;
}
//10+10+9*2+8*3+7+6*4+5*5+4+0+2*4+1+3=134
//ans=(n-prime[i][pos]+1)*(prime[i][pos]-prime[i][pos?1])
C. Berland Regional
题目链接
题意
有n个球员,每个球员都有属于自己的大学,属于自己的能力值,同一个大学的队员可以组队,人数不够则无法组队,问当队伍人数要求为k时,所有大学的队员能力数最多是多少?
题解
如题,直接暴力,每次放能力值最大的进去就好了,人数不够就不算
AC代码
#include "bits/stdc++.h"
using namespace std;
#define int long long
#define ll long long
const int maxn=1e6+10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
inline int rd()
{
int a;scanf("%lld",&a);return a;
}
int cmp(int a,int b){
return a>b;
}
signed main(){
ll t=rd();
while(t--){
ll n=rd();
map<ll, vector<ll>> mp;
vector<ll>a(n+1),sum(n+1);
for(int i=1;i<=n;i++)a[i]=rd();
for(int i=1;i<=n;i++) {
ll aa = rd();
mp[a[i]].push_back(aa);
}
for(auto it : mp ) {
sort(it.second.begin(), it.second.end(), cmp);
int len = it.second.size();
vector<ll>b(len+1);
for (int i = 1; i <= len; i++) {
b[i] = b[i - 1] + it.second[i-1];
}
for (int i = 1; i <= len; i++) {
sum[i] = sum[i] + b[len - len % i];
}
}
for(int i=1;i<=n;i++){
printf("%lld%c",sum[i],i==n?'\n':' ');
}
}
return 0;
}
D. Nezzar and Board
题目链接
题意
给一串数组x,可以选择其中两个进行2x-y操做,问能不能变成想要的数字k
题解
最终答案的形式必定为\(2x-y=x+(x-y)=k\)
即一个数加上另一个数和其本身的差值的和
也就是\(a_i+\sum_{i,k}(a_j-a_k)\)
\(\sum_{i,k}(a_j-a_k)=\sum_{i=2}^nf_i(a_i-a_{i-1}),f_i为系数\)
令\(g=gcd([a_i-a_{i-1}]),i\epsilon[2,n]\)
从裴蜀定理可知\(\sum_{i=2}^nf_i(a_i-a_{i-1})\)%\(g=0\)
因此只要判断\((k-a_i)\)%\(g==0\)
因为后面的数都可以用\(a_1+\sum(a_j-a_{j-1})\)得到
所以只要判断\((k-a_1)\)%\(g==0\)
AC代码
#include "bits/stdc++.h"
using namespace std;
#define int long long
#define ll long long
const int maxn=2e5+10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
inline int rd()
{
int a;scanf("%lld",&a);return a;
}
inline int gcd(int a,int b){
return !b? a:gcd(b,a%b);
}
int t;
int n,m;
int a[maxn];
signed main(){
t=rd();
while(t--){
n=rd();m=rd();
for(int i=1;i<=n;i++){
a[i]=rd();
}
int gcdd=0;
for(int i=2;i<=n;i++){
gcdd=gcd(a[i]-a[i-1],gcdd);
}
if((m-a[1])%gcdd==0)printf("YES\n");
else printf("NO\n");
}
return 0;
}

浙公网安备 33010602011771号