2017 ACM-ICPC 亚洲区(西安赛区)网络赛

 

A. Tree 题库链接【并查集+树上dfs】

 

(把每条路径先拆开拆成u->lca和lca->v(去掉lca),然后在树上dfs,回溯的时候把儿子挂到当前节点/带权并查集维护路径乘积)

 

 B. Coin 题库链接(√)【二项分布计算概率+乘法逆元+组合数学】

【题意】:一枚硬币,投一次正面朝上概率为q/p, 求投k次,正面朝上的次数为偶数次的概率X/Y,输出(XY​^(-1))mod(10​^9) .

就是求((p-q)/p+q/p*x)^k的偶次项系数之和,代入x=1,-1加加减减就行了 。

概率计算,但最终结果不用除法,用逆元。只算分子即可,分母就是p的k次幂。

https://wenku.baidu.com/view/8316d8390912a2161479297c.html?qq-pf-to=pcqq.group (二项分布中偶数项之和与奇数项之和
 
 
C. Sum 题库链接(√)【构造】
【题意】:是说有一个函数S(x)的值是一个数的十进制表示,所有位数之和。现在S(k*x)%233=0;问你K的是多少。当X=1的时候,K=89999999999999999999999999,S(k*x)=233就符合条件。

【分析】://这道题目就是个脑洞题,想到构造方法就可以了。
我们想到的构造方法是,1001*123=123123
那么我们就只需要233个123就一定是满足条件的
那么我们只需要233个1001这样的循环节,在乘以X以后就变成了一个233个123的数。这样的数的位数和一定是可以整除233的。
 
//1.任何数乘9的位数和都为9,直接输出233个9。因为任何正整数乘以9的数位和都是9的倍数。

2.需要找到一个k使得k*x之后的值,每一位上的值相加是233的倍数

那么我们可以想到,如果能够造一个k使得k*x上的每一位之和是x*233就行啦

再仔细看题,x最多取到1000000,所以我们打印233个0000001就行了,这样使得最后得到的每一位之和就是233个x。

//当x<10时可以直接输出233个x,当1000>x>=10时,不妨设k*x=233个x,那么k=10(233个10),当1000<=x<10000,k=100(233个100),等等。手动模拟一下就懂了。
 
 
E. Maximum Flow 题库链接 【通过最大流模板找出规律】
 

【分析】:打印出来相邻两个数的差是有规律的, 差值的规律如下:

2^0+1 第一次出现的位置为2^1, 第二次出现的位置为2^1+2^0,  接下来出现的位置依次为:2^1+2^0+k*2^1;

2^2+1 第一次出现的位置为2^2, 第二次出现的位置为2^2+2^1,  接下来出现的位置依次为:2^2+2^1+k*2^2;

2^4+1 第一次出现的位置为2^3, 第二次出现的位置为2^3+2^2,  接下来出现的位置依次为:2^3+2^2+k*2^3;

2^6+1 第一次出现的位置为2^4, 第二次出现的位置为2^4+2^3,  接下来出现的位置依次为:2^4+2^3+k*2^4;

 
上下双阶乘可约掉一部分, 除法用逆元,还有判断一下m和n的一些特殊值
 
 
<——公式
  1. 当m大于n时,答案显然为0。
  2. 当n为奇数且m为偶数或n为偶数且m为奇数时答案显然为0。
  3. 当n为奇数,且m为1时,答案的绝对值为n。
  4. 当n为偶数,且m为0时,答案的绝对值为1。
  5. 其余情况答案的绝对值均为【 n * (n-m+2) * (n-m+4) * ... * (n+m-4) * (n+m-2) 】/(m!)。(注意逆元的运用)
  6. 上面出现绝对值的情况,3和4 当(n/2)%2 == 0 时符号为正,否则为负;5 当((n-m)/2)%2 == 0时,符号为正,否则符号为负。
 
F. Trig Function 题库链接 【切比雪夫多项式+双阶乘+化简】
 
 求出k然后比较分子分母大小然后从小的开始+=2算出双阶乘就好了 
 
 
G. Xor 题库链接 【分块+预处理】
类似HDU 5840,K大则暴力跳,K 小预处理跳到根的值/加加减减。
 
 
I. Barty's Computer 题库链接 【五维偏序+bitset】
转化为五维偏序->bitset裸五维数点->直接sort+lower_bound/暴力匹配*4
 
 

 
B:
#include <iostream>
#include <cstdio>
using namespace std;

typedef long long ll;

void exgcd(ll a,ll b,ll& d,ll& x,ll& y)
{
    if(!b) { d = a; x = 1; y = 0; }
    else{ exgcd(b, a%b, d, y, x); y -= x*(a/b); }
}

ll inv(ll a, ll p)
{
    ll d, x, y;
    exgcd(a, p, d, x, y);
    return d == 1 ? (x+p)%p : -1;
}
int mod=1e9+7;
ll find1(int x,int n)  //注意n等于0的时候
{
    ll a=x;
    ll ans=1;
    while (n)
    {
        if (n&1) ans=ans*a%mod;
        a=a*a%mod;
        n>>=1;//效果跟n/=2;一样
    }
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll p,q,k;
        ll x,y;
        scanf("%lld%lld%lld",&p,&q,&k);
        if(p>q)
        {
            ll t=q;
            q=p;
            p=t;
        }
        x=q-2*p;
        y=q;
        x=find1(x,k);
        y=find1(y,k);
        x=(x+y)%mod;
        y=(2*y)%mod;
       // printf("%lld  %lld   ",x,y);
        printf("%lld\n",(x*inv(y,mod))%mod);
    }
}
B题-二项分布公式题/注意逆元
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
long long POW(long long x,long long n)
{
    long long res=1;
    while(n)
    {
        if(n&1)res=(res*x)%MOD;
        x=(x*x)%MOD;
        n/=2;
    }
    return res;
}
int main()
{
    int T;cin>>T;
    while(T--)
    {
        long long p,q,k;
        scanf("%lld%lld%lld",&p,&q,&k);
        long long x=POW(p-2*q,k);
        long long y=POW(p,k);
        cout<<(  ((1+x*POW(y,MOD-2))%MOD) * POW(2,MOD-2) )%MOD<<endl;
    }
    return 0;
}
参考http://blog.csdn.net/Mitsuha_/article/details/78005772?locationNum=5&fps=1
#include <iostream>  
#include <stdlib.h>  
#include <string.h>  
#include <stdio.h>  
#include <queue>  
#include <algorithm>  
using namespace std;  
typedef long long ll;  
const int maxn=3;  
struct Matrix//????  
{  
  ll a[maxn][maxn];  
  void init()            
  {  
    memset(a,0,sizeof(a));  
    for(int i=1;i<maxn;i++)  
      a[i][i]=1;  
  }  
}  ;  
const ll mod=1000000007;  
Matrix mul(Matrix a,Matrix b)  //(a*b)%mod  ????  
{  
  Matrix ans;  
  memset(ans.a,0,sizeof(ans.a));  
  for(int i=1;i<maxn;i++)  
    for(int j=1;j<maxn;j++)  
    {  
      ans.a[i][j]=0;  
      for(int k=1;k<maxn;k++)  
        {  
            ans.a[i][j]+=a.a[i][k]*b.a[k][j] ;  
            ans.a[i][j]%=mod;  
        }  
    }  
    return ans;  
}  
  
Matrix pow(Matrix a,ll m)  
{  
    Matrix res ;  
    memset(res.a,0,sizeof(res.a));  
    for(int i=1;i<maxn;i++)  
    {  
        res.a[i][i]=1;  
    }  
    while(m)  
    {  
        if(m&1)  
        {  
            res=mul(a,res);  
        }  
        a=mul(a,a);  
        m/=2;  
    }  
    return res;  
  
}  
  
ll quick(ll n,ll m)  
{  
    ll ans = 1;  
    while(m){  
        if(m & 1)  
            ans = ans * n % mod;  
        m >>= 1;  
        n = n * n % mod;  
    }  
    return ans;  
}  
int main()  
{  
    double p;  
    int t=0;  
    int n;  
    scanf("%d",&t);  
    while(t--)  
    {  
        ll p,q,k;  
        scanf("%lld%lld%lld",&p,&q,&k);  
        ll nums=    q*quick(p,mod-2)%mod;  
        ll numx=(p-q)*quick(p,mod-2)%mod;  
        Matrix ans;  
        ans.a[1][1]=(numx)%mod;  
        ans.a[2][1]=(nums)%mod;  
  
      //  printf("%lld\n",quick(27,mod-2)%mod*14%mod);  
      /*  ll pp = (numx * numx % mod + nums * nums % mod) % mod; 
        ll qq = (numx * numx) % mod; 
        printf("%lld\n",(pp * numx % mod + qq * nums % mod) % mod);*/  
        if(k==1)  
        {  
            printf("%lld\n",ans.a[1][1]%mod);  
            continue;  
        }  
        Matrix base,res;  
        base.a[1][1]=numx,base.a[1][2] =nums;  
        base.a[2][1]=nums,base.a[2][2]= numx;  
        res=pow( base, k - 1 );  
        ans=mul( base,res);  
        printf("%lld\n",ans.a[1][1]%mod);  
    }  
}  

//http://blog.csdn.net/qq_33951440/article/details/78005483
矩阵优化dp版
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
typedef long long ll;
ll p, q, n;

ll qmod(ll x, ll q)
{
    ll res = 1;
    while(q)
    {
        if(q%2) res = res*x%mod;
        x = x*x%mod;
        q /= 2;
    }
    return res;
}

int main(void)
{
    int _;
    cin >> _;
    while(_--)
    {
        scanf("%lld%lld%lld", &p, &q, &n);
        ll ni2 = qmod(2LL, mod-2);
        ll fm = qmod(p, n);
        ll fz = qmod(p-2*q, n);
        ll nifm = qmod(fm, mod-2);
        ll tmp = (1+fz*nifm%mod)%mod*ni2%mod;
        printf("%lld\n", tmp);
    }
    return 0;
}
参考http://blog.csdn.net/cillyb/article/details/78005332

 

C:

#include<cstdio>
#include<iostream>
#include<cstring>

using namespace std;

int main()
{
    int t,x;
    scanf("%d",&t);
    while(t--){
        cin>>x;
        printf("1");
        for(int i=2;i<=233;i++)
        {
            printf("0000001");
        }
        printf("\n");
    }
    return 0;
}
出0题/构造

 

E: http://www.docin.com/p-385138324.html?qq-pf-to=pcqq.group 【用以表示cosnx的关于cosx的多项式的通项公式

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll sum[100];
ll la[100];
ll two[100];
int main()
{
    sum[0]=1;
    la[0]=1;
    two[0]=1;
    for(int i=1; i<=64; i++)
    {
        two[i]=two[i-1]*2ll;
        sum[i]=(sum[i-1]*2%mod+la[i-1]*3%mod)%mod;
        la[i]=la[i-1]*4%mod;
    }
    ll n;
    while(~scanf("%lld",&n))
    {

        n--;
        ll pos;
        for(ll i=62; i>=0; i--)
        {
            if(n>=two[i])
            {
                pos=i;
                break;
            }
        }
        ll ans=n%mod;
//        cout<<pos<<endl;
        pos=(1ll<<pos);
        n-=pos;
        ans+=((1ll*pos/2ll)%mod)*((pos-1ll)%mod);
        ans%=mod;
        for(ll i=0; i<63; i++)
        {
            if(n&(1ll<<i))
                ans+=sum[i];
            ans%=mod;
        }
        printf("%lld\n",ans%mod);
    }
}
公式题1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;

const int MAXN = 30010;

string lib[MAXN];
int tot;

int cmpa(string &str, string &a){
    for(int i = 0; i < a.length(); ++i){
        if(str[i] != a[i]){
            return 0;
        }
    }
    return 1;
}

int cmpd(string &str, string &d){
    for(int i = 1; i <= d.length(); ++i){
        if(str[str.length() - i] != d[d.length() - i]){
            return 0;
        }
    }
    return 1;
}

int cmpbc(string &str, string &b, string &c){
    int mid = str.length() / 2;
    for(int i = 0; i < c.length(); ++i){
        if(str[mid + i] != c[i]){
            return 0;
        }
    }
    for(int i = 1; i <= b.length(); ++i){
        if(str[mid - i] != b[b.length() - i]){
            return 0;
        }
    }
    return 1;
}

int main(){
    ios::sync_with_stdio(false);
    int T, q;
    for(cin >> T; T && cin >> q; --T){
        tot = 0;
        int ctrl;
        for (int k = 0; k < q; ++k)
        {
            cin >> ctrl;
            if (ctrl == 1)
            {
                cin >> lib[tot++];
            }
            else
            {
                string a, b, c, d;
                cin >> a >> b >> c >> d;
                int maxLen = a.length() + b.length();
                if (c.length() + d.length() > maxLen)
                    maxLen = c.length() + d.length();
                maxLen *= 2;
                int cnt = 0;
                for (int i = 0; i < tot; ++i)
                {
                    if (lib[i].length() >= maxLen && lib[i].length() % 2 == 0)
                    {
                        if (cmpa(lib[i], a) && cmpd(lib[i], d) && cmpbc(lib[i], b, c))
                        {
                            ++cnt;
                        }
                    }
                }
                cout << cnt << endl;
            }
        }
    }
    return 0;
}
二发

 

F:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<utility>
#include<numeric>
#include<iterator>
#include<algorithm>
#include<functional>
#include<ctime>
#include<cassert>
using std::cin;
using std::cout;
using std::endl;
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int,int> P;
#define FOR(i,init,len) for(int i=(init);i<(len);++i)
#define For(i,init,len) for(int i=(init);i<=(len);++i)
#define fi first
#define se second
#define pb push_back
#define is insert
namespace IO {
    inline char getchar() {
        static const int BUFSIZE=5201314;
        static char buf[BUFSIZE],*begin,*end;
        if(begin==end) {
            begin=buf;
            end=buf+fread(buf,1,BUFSIZE,stdin);
            if(begin==end) return -1;
        }
        return *begin++;
    }
}
inline void read(int &in) {
    int c,symbol=1;
    while(isspace(c=IO::getchar()));
    if(c=='-') { in=0;symbol=-1; }
    else in=c-'0';
    while(isdigit(c=IO::getchar())) { in*=10;in+=c-'0'; }
    in*=symbol;
}
inline int read() { static int x;read(x);return x; }
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; }
ll lcm(ll a,ll b) { return a/gcd(a,b)*b; }

const ll mod=998244353LL;
const int maxm=1e4+10;
ll qpow(ll a,ll b) {
    ll ans=1;
    while(b) {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
ll f[maxm],invf[maxm];
ll n,m;

int main() {
#ifdef MengLan
    int Beginning=clock();
    //freopen("in","r",stdin);
    //freopen("out","w",stdout);
#endif // MengLan

    f[0]=1;
    FOR(i,1,maxm) f[i]=f[i-1]*i%mod;
    invf[maxm-1]=qpow(f[maxm-1],mod-2);
    for(int i=maxm-2;i>=0;--i) invf[i]=invf[i+1]*(i+1)%mod;
    while(cin>>n>>m) {
        if((n&1)^(m&1)) { puts("0");continue; }
        if(m>n) { puts("0");continue; }
        if(m==0) { puts("998244352");continue; }
        ll ans=1;
        for(ll i=n-m+2;i<=n+m-2;i+=2) { ans*=i;ans%=mod; }
        ans=ans*n%mod;
        ll k=1;
        For(i,1,m) { k=k*i%mod; }
        ll x=qpow(k,mod-2);
        ans=ans*x%mod;
        if(((n-m)/2)&1) ans=(mod-ans)%mod;
        cout<<ans<<endl;
    }

#ifdef MengLan
    printf("Time: %d\n",clock()-Beginning);
#endif // MengLan
    return 0;
}
FFFFF
#include<cstdio>
using namespace std;
typedef long long LL;
const LL MOD=998244353;
LL quick_pow(LL y,LL k)
{
    LL res = 1;
    while (k)
    {
        if (k & 1)
            res=(res* y)%MOD;
        y=(y*y)%MOD;
        k >>= 1;
    }
    return res;
}


LL fun1(LL n)
{
    LL t=1;
    for(LL i=n;i>=1;i--)
       t=(t*i)%MOD;
    return t;

}
LL fun2(LL n,LL m)
{
        LL count=1;
        while(n>m)
        {
            count=(count*n)%MOD;
            n=n-2;
        }
        return count;
}
int main()
{
       LL n,m;
       while(~scanf("%lld%lld",&n,&m))
       {

          if(n%2!=m%2||m>n)
          {
            printf("0\n");
            continue;
          }

          if(m==0)
          {
              printf("998244352\n");
              continue;
          }

          LL x,y;
          x=(n*fun2(n+m-2,n-m))%MOD;
          y=fun1(m);
          LL a=quick_pow(y,MOD-2);
          LL ans=(x*a)%MOD;
          if((n-m)/2%2)
           ans=(MOD-ans)%MOD;

          printf("%lld\n",ans);
       }
}
注意除法用乘法逆元

 

 

posted @ 2017-09-16 17:32  Roni_i  阅读(1107)  评论(0编辑  收藏  举报