2018暑假杭电多校第七场

版权声明:转载请注明出。。。不转不是中国人~~~ https://blog.csdn.net/SwustLpf/article/details/81699163

GuGuFishtion (hdu 6390 莫比乌斯反演)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6390

φ((ab)φ(a)φ(b)=gcd(a,b)φ(gcd(a,b))

关于这个公式的化简。。。看这个
其实就是求:
所有的 gcd=1 的时候的 11φ(1)
所有的 gcd=2 的时候的 21φ(2)
所有的 gcd=3 的时候的 31φ(3)
所有的 gcd=4 的时候的 41φ(4)

而求 gcd=d的个数不就是很经典的莫比乌斯的题么,我这里就是 f(d) 表示 gcd=d的个数,F(d) 表示 gcd=d 的倍数的个数

#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int maxn=1e6+5;
int MOD=1e9+7;
bool vis[maxn];
int phi[maxn];
int mu[maxn]; 
int Smu[maxn];
int inv[maxn]={1,1};
int T,N,M;
vector<int>prime;
void PHI(int n)
{
    memset(vis,1,sizeof(vis));
    phi[1]=1;
    mu[1]=1;
    Smu[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(vis[i])
        {
            prime.push_back(i);
            phi[i]=i-1;
            mu[i]=-1;
        }
        for(int j=0;j<prime.size()&&i*prime[j]<=n;j++)
        {
            vis[i*prime[j]]=0;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                mu[i*prime[j]]=0;
                break;
            }
            else
            {
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
                mu[i*prime[j]]=-mu[i];
            }
        }
        Smu[i]=Smu[i-1]+mu[i];
    }
}
LL F(int n)//求gcd=n的倍数的个数
{
    return (LL)(N/n)*(M/n);
} 
LL f(int n)求gcd=n的个数
{
    LL res=0;
    for(int i=1,j,d=n;d<=N;i=j+1)
    {

        j=min(N/(N/i),(M/(M/i)));
        res+=(LL)(Smu[j]-Smu[i-1])*F(d);
        if(res>MOD)res%=MOD;
        d+=(j-i+1)*n;

    }
    return res;
}
LL ksm(LL a,LL b,LL mod)
{
    LL res=1,base=a;
    while(b)
    {
        if(b&1)res=(res*base)%mod;
        base=(base*base)%mod;
        b>>=1;
    }
    return res;
}
int main()
{
    PHI(1e6);

    cin>>T;
    while(T--)
    {
        cin>>N>>M>>MOD;
        if(N>M)swap(N,M);
        LL res=0;
        for(int i=1;i<=N;i++)
        {
            if(i>1)inv[i]=(LL)(MOD-MOD/i)*inv[MOD%i]%MOD;
            res+=(LL)f(i)*i%MOD*inv[phi[i]]%MOD;
            if(res>MOD)res%=MOD;
        }
        cout<<res<<endl;
    }
}```

#Sequence(hdu 6395 分段矩阵快速幂)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6395

比赛完之后再看这道题,其实也没有什么。。。
这道题最关键的就是怎么快速的分段
其实这也是非常常见的手法,在莫比乌斯反演的裸题以及杜教筛什么的都有:
就是在 $[i,\frac{x}{x/i}]$这段区间内,$\frac{x}{i}$的值是一样的,而且只有 $sqrt(x)个值$

include”bits/stdc++.h”

using namespace std;
typedef long long LL;
const int MOD=1e9+7;
struct Matrix
{
int n;
LL a[3][3];
Matrix (int n):n(n)
{
for(int i=0;i


#Swordsman(hdu 6396)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6396
题意:就是说有 $n$ 个怪,最多有 $5$ 种属性,自己也有$5$ 种属性,要在自己的每种属性都大于怪的每种属性的时候,就阔以把怪杀死,并且自己的属性还会得到对应的提升
问:最多能杀多少怪,以及最后自己的每个属性的值是多少?

参考博客:昨天看的今天写的。。。然后就没找到这位童鞋的博客T_T

这道题我参考的这位童鞋的思路感觉非常好懂:
就是先把每个属性从小到大排序,把比自己小的属性先记录下来,用一个 $sum[i]$ 表示第 $i$ 个怪物记录了多少属性,然后在看如果某个怪物的 $sum$ 达到了 $K$ 个,那么就把这个怪物吃了就行了

然后这道题还非要输入挂,于是又从那位童鞋那里得到了一个优秀的输入挂
~~原来以前的 getchar 那种挂是假的挂啊,,,我才知道~~

include”bits/stdc++.h”

define out(x) cout<<#x<<”=”<

define C(n,m) ((long long)fac[(n)]*inv[(m)]%MOD*inv[(n)-(m)]%MOD)

using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int MOD=1e9+7;

//优秀的输入挂
namespace fastIO {
#define BUF_SIZE 100000
//fread -> read
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ’ ’ || ch == ‘\n’ || ch == ‘\r’ || ch == ‘\t’;
}
inline void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror) return;
for(x = ch - ‘0’; (ch = nc()) >= ‘0’ && ch <= ‘9’; x = x * 10 + ch - ‘0’);
}
#undef BUF_SIZE
};
//using namespace fastIO;

int N,K;
struct AAA
{
int v,id;
bool operator<(const AAA &t)const
{
return v

展开阅读全文

没有更多推荐了,返回首页