记录一个菜逼的成长。。
2017 Multi-University Training Contest - Team 2
题目链接
题目大意:
给你
A
序列,问有多少个
1.
1≤Bi≤Ai
2.任意一个区间
[l,r]
的
gcd>=2
笔记
官方题解:
令
F(i)
表示是
i
倍数的方案数,可以容易的通过预处理出前缀和后在
预处理前缀和是因为可以对一个区间进行统一操作。
比如当
gcd==2
时,区间
[4,5]
除以
2
的值都是
最后莫比乌斯容斥。
#include <bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for( int i = l; i <= r; i++ )
#define rep0(i,l,r) for( int i = l; i < r; i++ )
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
#define mp make_pair
typedef long long LL;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const LL MOD = 1e9+7;
const int maxn = 100000 + 10;
int a[maxn],sum[maxn<<1];
bool check[maxn];
int mu[maxn],prime[maxn];
void Mobius()
{
cl(check,false);
mu[1] = 1;
int tot = 0;
for( int i = 2; i < maxn; i++ ){
if(!check[i]){
prime[tot++] = i;
mu[i] = -1;
}
for( int j = 0; j < tot; j++ ){
if(i * prime[j] >= maxn)break;
check[i*prime[j]] = true;
if(i % prime[j] == 0){
mu[i * prime[j]] = 0;
break;
}
else {
mu[i * prime[j]] = -mu[i];
}
}
}
}
LL Pow(LL a,LL b,LL c)
{
LL ret = 1;
while(b){
if(b&1)ret = ret * a % c;
b >>= 1;
a = a * a % c;
}
return ret;
}
int main()
{
Mobius();
int T,cas = 1;scanf("%d",&T);
while(T--){
cl(sum,0);
int n,mn = maxn;
scanf("%d",&n);
rep(i,1,n)scanf("%d",a+i),mn = min(mn,a[i]),sum[a[i]]++;
rep0(i,1,maxn<<1)sum[i] += sum[i-1];
LL ans = 0;
rep(i,2,mn){
LL num = 1;
for( int j = 1; j * i <= 100000; j++ ){
//在这个区间内的每个a_i都有j个取值。
num *= Pow(j,sum[i * (j + 1) - 1] - sum[i * j - 1],MOD);
num %= MOD;
}
//ans = (ans - mu[i] * num) % MOD;
}
//printf("Case #%d: %lld\n",cas++,MOD - (ans + MOD) % MOD);
printf("Case #%d: %lld\n",cas++,(ans + MOD) % MOD);
}
return 0;
}