2018.6清北学堂day6考试

T1

给定一个n和k,求可爱数字的个数

其中可爱的数字满足

{ s K i } > S K n

对于实数 x , { x } 表示x的小数部分。

n , k 10 9

QwQ这道应该是全场最难的题了

题解:观察一下题目中的那个式子,不难看出其实有点像把n转成k进制,那么,如果一个数转成k进制之后,是非周期的(就是依次从最后移动到最前,所有的数都不一样),那么一定有一个数满足这个式子,也就是最小的那个


并且….k进制下最小的循环节d一定是满足 d | n

有一个惊人的发现:我们将非周期的求出来…..就能发现… a n s = n × n u m

其中长度为n的非循环节的数的个数可以通过dp来求

首先呢,我们考虑,我们求非循环节的个数,实际上就是总数减去所有有循环节的个数

那么总数就是 q s m ( k , i )

那么有循环节的呢?

我们考虑能够成循环节的,一定是i的因数,且每一个节循环节内部没有循环节,否则就会重复计数,所以我们就是对于每一个 d | i , f [ i ] = f [ d ] 就可以

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;

inline int read()
{
  int x=0,f=1;char ch=getchar();
  while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
  while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}

const ll mod = 1e9+7;

ll n,k,f[1000010];
ll mul[1000010];

ll qsm(ll i,ll j)
{
    ll ans=1;
    while (j)
    {
        if (j&1) ans=ans*i%mod;
        i=i*i%mod;
        j>>=1;
    }
    return ans;
}

ll cnt;

int main()
{
  cin>>n>>k;
  for (ll i=1;i*i<=n;i++)
  {
     if (n%i==0)
     {
        mul[++cnt]=i;
        if (i*i<n) mul[++cnt]=n/i;
       }
  }
  sort(mul+1,mul+1+cnt);
  for (ll i=1;i<=cnt;i++)
  {
     f[i]=qsm(k,mul[i]);
     for (ll j=1;j<=i-1;j++)
     if (mul[i]%mul[j]==0) f[i]=(f[i]-f[j]+mod)%mod;    
  } 
  printf("%lld",f[cnt]*qsm(n,mod-2)%mod); 
  return 0;
}

T2

a b c mod p 的值

其中 a , b , c , p 10 9

保证p是质数

十分简单,根据费马小定理,我们可以直接把 b c mod ( p 1 ) 然后再算快速幂就好

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;

ll a,b,c,p;

ll qsm(ll i,ll j,ll mod)
{
    ll ans=1;
    i=i%mod;
    while (j)
    {
        if (j&1) ans=ans*i%mod;
        i=i*i%mod;
        j>>=1;
    }
    return ans;
}

int main()
{
  freopen("number.in","r",stdin);
  freopen("number.out","w",stdout);
  cin>>a>>b>>c>>p;
  //cout<<qsm(a,b,c)<<endl;
  ll tmp = qsm(b,c,p-1);
  cout<<qsm(a,tmp,p);
  return 0;
}

T3
f ( x ) 表示n的所有正约数的平方和,输入n和 P ,你只需要输出 i = 1 n f ( x )

解法:我们考虑,对于每个约数i,我们其实就是求的 i = 1 n i 2 × n i

那么 n i 这个东西可以整除分块

同时 1 2 + 2 2 + 3 2 = n ( n + 1 ) ( 2 n + 1 ) 6

对于一段区间 [ i , j ] ,直接用 ( n / i ) ( c o u n t ( j ) c o u n t ( i 1 ) 就行,注意取膜的一些小细节

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long

using namespace std;

ll ans;
ll n;
ll p;
ll inv;

ll qsm(ll i,ll j)
{
    ll ans=1;
    while (j)
    {
        if (j&1) ans=ans*i%p;
        i=i*i%p;
        j>>=1;
    }
    return ans;

}

ll count(ll x)
{
    x=x%p;
    return x*(x+1)%p*(2*x+1)%p*inv%p;
}

int main()
{
  freopen("sos.in","r",stdin);
  freopen("sos.out","w",stdout);
  cin>>n>>p;
  inv = qsm(6,p-2);
  for (ll i=1,j;i<=n;i=j+1)
  {
    j=n/(n/i);  
    ans=(ans+(n/i)*((count(j)-count(i-1)+p)%p)%p)%p;
    //cout<<i<<" "<<j<<" "<<ans<<endl;
  }
  cout<<ans;
  return 0;
}

猜你喜欢

转载自blog.csdn.net/y752742355/article/details/80656497
今日推荐