Codeforces Beta Round #17 D题 福大核武 景润后人!!!

D. Notepad
time limit per test
2 seconds
memory limit per test
64 megabytes
input
standard input
output
standard output

Nick is attracted by everything unconventional. He doesn't like decimal number system any more, and he decided to study other number systems. A number system with base b caught his attention. Before he starts studying it, he wants to write in his notepad all the numbers of length n without leading zeros in this number system. Each page in Nick's notepad has enough space for c numbers exactly. Nick writes every suitable number only once, starting with the first clean page and leaving no clean spaces. Nick never writes number 0 as he has unpleasant memories about zero divide.

Would you help Nick find out how many numbers will be written on the last page.

Input

The only input line contains three space-separated integers b, n and c (2 ≤ b < 10106, 1 ≤ n < 10106, 1 ≤ c ≤ 109). You may consider that Nick has infinite patience, endless amount of paper and representations of digits as characters. The numbers doesn't contain leading zeros.

Output

In the only line output the amount of numbers written on the same page as the last number.

Sample test(s)
Input
2 3 3
Output
1
Input
2 3 4
Output
4
Note

In both samples there are exactly 4 numbers of length 3 in binary number system. In the first sample Nick writes 3 numbers on the first page and 1 on the second page. In the second sample all the 4 numbers can be written on the first page.

是TXY叫我看这题的,说要用到EULER函数,然后看了一下,发现羊神跪了10次放弃了,搞得我不敢去敲,结果发现是TOURIST出的题,更让我跪了,后来她说WUST的人出

了这题,结果一看是阿峰出的= =表示抱着不服输的心态来看题了。。。

说白了就是让你求(b^n-1*(b-1))%c的值,如果为0输出c即可

思路:b n 大的都吓得鬼都见不得,字符读入来模拟,b好办,每次模拟过程中取模c即可,但是n怎么办,没膜拜过福大核武写的指数循环节博客的人基本只有GG的份,还好我膜拜过,所以知道可以用欧拉函数降幂也即A^Bmod C=(A^Bmodphi(C)+phi(C))modC来求解(千万注意要B>phi(c)时才能取模否则又是GG),这样TXY说的为什么要求EULER函数就很明显了,然后接下来就是EGGS PAIN的模拟了,对N的模拟分两部分,如果N模拟完毕之后都比C小,就直接快速幂,否则重新模拟,在模拟的过程中每次对phi(c)取模即可,这样N即使很大也能在多次降幂中把它给降下来,然后再进行快速幂即可,然后写的时候又忘了+phi(c)跪了一次T T,题意没完全读懂跪了两次,还好是比赛后可以看数据,如果真要是比赛的时候,尼玛知道做法到最后肯定还是跪的,最后,福大核武 景润后人,6666666!

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
char b[1000005];
char n[1000005];
long long c;

long long euler(long long n)
{
    long long res=n;
    for(long long i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            res=res/i*(i-1);
            while(n%i==0)
            {
                n/=i;
            }
        }
    }
    if(n!=1)
    {
        res=res/n*(n-1);
    }
    return res;
}
long long power(long long a,long long b,long long mod)
{
    long long res=1;
    while(b)
    {
        if(b&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}
int main()
{
    cin>>b>>n>>c;
    long long rb=0;
    for(long long i=0;b[i]!='\0';i++)
    {
        rb=(rb*10+b[i]-'0')%c;
    }
    long long res=0;
    long long phi=euler(c);
    bool flag=0;
    for(long long i=0;n[i]!='\0';i++)
    {
        res=(res*10+n[i]-'0');
        if(res>c)
        {
            flag=1;
            break;
        }
    }
  // cout<<flag<<endl;
    if(flag==1)
    {
        long long ans1=0;
        //cout<<phi<<endl;
        for(long long i=0;n[i];i++)
        {
            ans1=(ans1*10+n[i]-'0')%phi;
           // cout<<ans1<<endl;
            //return 0;
        }

        long long ans2=(ans1-1+phi)%phi;
        long long pp=power(rb,ans1+phi,c);
        long long qq=power(rb,ans2+phi,c);
        if((pp-qq+c)%c)
        cout<<(pp-qq+c)%c<<endl;
        else
            cout<<c<<endl;

    }
    else
    {

        long long nn=power(rb,res,c);
        long long mm=power(rb,res-1,c);
        if((nn-mm+c)%c)
        cout<<(nn-mm+c)%c<<endl;
        else
            cout<<c<<endl;
    }
    return 0;
}


目描述 给定一棵 $n$ 个节点的树,每个节点都有一个权值 $w_i$。你需要删去树上的一些边,使得剩下的每个连通块中,所有节点的权值之和不超过 $k$。 求最多能删去多少条边。 输入格式 第一行包含两个整数 $n,k$。 第二行包含 $n$ 个整数 $w_1,w_2,\cdots,w_n$。 接下来 $n-1$ 行,每行包含两个整数 $a,b$,表示节点 $a$ 和节点 $b$ 之间有一条边。 输出格式 输出一个整数,表示最多能删去的边数。 数据范围 $1\le n \le 10^5$ $1 \le k,w_i \le 10^9$ 输入样例1: 5 6 2 3 1 5 4 1 2 1 3 2 4 2 5 输出样例1: 2 输入样例2: 5 3 2 3 1 5 4 1 2 1 3 2 4 2 5 输出样例2: 0 算法1 (dfs) $O(n)$ 首先我们可以想到暴力的做法,即对于每个连通块,暴力枚举删去哪些边,尝试得到最多的删边数。那么如何求解一个连通块内的所有节点权值之和呢?我们可以使用 DFS 遍历树,对于每个节点,求出其子树内所有节点的权值之和,那么以该节点为根的子树内的所有节点权值之和就是该节点自身的权值加上其所有子节点的权值之和。 对于每个连通块,我们枚举该连通块内任意两个节点 $x,y$。如果 $x$ 与 $y$ 之间的路径上的所有边都被删去了,那么 $x$ 和 $y$ 就会分别成为两个新的连通块,这两个新的连通块内所有节点的权值之和都不超过 $k$。因此我们只需要枚举所有的 $x,y$ 对,对于每个 $x,y$ 对尝试删去它们之间的路径上的所有边,看是否能够让 $x$ 和 $y$ 成为两个新的连通块,进而更新答案即可。 时间复杂度 参考文献 python3 代码 算法2 (暴力枚举) $O(n^2)$ blablabla 时间复杂度 参考文献 C++ 代码 class Solution { public: const int N = 1e5+10; int n,k; int h[N],e[N<<1],ne[N<<1],idx; int w[N]; int sum[N]; bool st[N]; int res; void add(int a,int b) { e[idx] = b,ne[idx] = h[a],h[a] = idx++; } void dfs(int u,int father) { sum[u] = w[u]; for(int i=h[u];~i;i=ne[i]) { int j = e[i]; if(j == father) continue; dfs(j,u); sum[u] += sum[j]; } } void dfs2(int u,int father) { for(int i=h[u];~i;i=ne[i]) { int j = e[i]; if(j == father) continue; dfs2(j,u); if(sum[j] <= k) res++; else if(sum[u] - sum[j] <= k) res++; } } void solve() { cin >> n >> k; memset(h,-1,sizeof(h)); for(int i=1;i<=n;i++) cin >> w[i]; for(int i=1;i<n;i++) { int a,b; cin >> a >> b; add(a,b); add(b,a); } dfs(1,-1); dfs2(1,-1); cout << res << endl; } }; int main() { Solution().solve(); return 0; }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值