Gym

A - The game of Osho

题意:每次给你G堆石子,每堆有(n{_i})个,一次可挑走(B{_i}^k)个。最后不能选的人输。问最后先手赢还是后手赢。

思路:从SG表的方式入手。
(B{_i})为奇数时,任意次幂也为奇数,此时若n为奇数,那么第一个人拿走若干后一定剩下是偶数个,第二个人再拿剩下的肯定是奇数个。以此类推此时永远是第一个人拿完后是偶数,所以最后拿到0的那一步也是第一个人拿走的,此时先手必胜。反之后手必胜。所以sg = n&1。
(B{_i})为偶数时,(B^k) = ((B+1 -1)^k),展开后对(B+1)取余,只有1和B两种情况(二项展开式的第一项为1或-1),那么n可以看出n = k*(B+1) + T, 0<=T<=B,若T小于B,只和T奇偶性有关。若T等于B,画一下sg函数可以知道此时sg为2(两个后继0和B-1,sg分别是0和1)。
最后依照上述判别方式将sg异或起来即可判断。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll sg[105];
vector<ll> f;
ll n, b;

int main()
{
    freopen("powers.in","r",stdin);
    int kase;
    cin>>kase;
    while(kase--)
    {
        int G = read();mem(sg,0);
        rep(i,1,G)
        {
            b = read(), n = read();
            if(b&1) sg[i] = n&1;
            else
            {
                ll m = n%(b+1);
                if(m==b) sg[i] = 2;
                else sg[i] = m&1;
            }
        }
        ll ans = 0;
        rep(i,1,G) ans ^= sg[i];
        puts(ans?"1":"2");
    }
    return 0;
}


D - Popcorn

排列组合签到题

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

inline ll C(ll n,ll m){return (ll)round(tgamma(n+1)/tgamma(m+1)/tgamma(n-m+1));}
int main()
{
    freopen("popcorn.in", "r", stdin);
    int kase;
    cin>>kase;
    while(kase--)
    {
        ll n = read(), m = read();
        cout<<C(n,m)<<endl;
    }
    return 0;
}


E - Jumping

题意:给你n个数,每个a[i]代表可以由i移动到(i-a[i])或者(i+a[i]),然后让你输出每个点到n点的最小跳跃次数。

思路:这个题当成最短路做就是模板题。在每个点可以移动到(i-a[i])或者(i+a[i]),那就让i和这两个点建反向边,权值为1,然后跑一个以n为起始点的最短路,采用Dijkstra堆优化,然后输出每个d[i]即可。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define endl '
'
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int maxn = 1e6+5;
const ll inf=0x3f3f3f3f3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') ch = getchar();while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
const int V = 2e5, E=2e5;
ll d[V],cost[E];
ll n,m;
ll head[V],pnt[E],nxt[E],e=1;
ll vis[V];
ll a[V];

inline void addedge(ll u,ll v,ll c)
{
    pnt[e]=v;       //当前以u为顶点,c为边长的,到v的一条边
    cost[e]=c;      //存入当前边权值
    nxt[e]=head[u];     //下一个其实是前一个
    head[u]=e++;        //当前边编号
}

inline void Dijkstra(ll s)
{
    //mem(d,inf); mem(vis,0);
    priority_queue<PII, vector<PII>, greater<PII> > q;
    d[s] = 0;
    q.push(mp(0LL,s));
    while(!q.empty())
    {
        ll x = q.top().se; q.pop();
        if(vis[x]) continue;
        vis[x] = 1;
        for(int i=head[x];i;i = nxt[i])
        {
            ll v = pnt[i];
            if(d[v]>d[x]+cost[i]&&!vis[v])
            {
                d[v] = d[x] + cost[i];
                q.push(mp(d[v], v));
            }
        }
    }
}

int main()
{
    freopen("jumping.in", "r", stdin);
    int kase;
    scanf("%d",&kase);
    while(kase--)
    {
        e = 1;
        n = read();
        rep(i,1,n) d[i] = inf, vis[i] = 0, head[i] = 0;
        rep(i,1,n)
        {
            ll d = read();
            ll x = i;
            if(x+d<=n)
            addedge(x+d,x,1);
            if(x-d>0)
            addedge(x-d,x,1);
        }
        Dijkstra(n);
        rep(i,1,n) if(d[i]!=inf) cout<<d[i]<<endl; else cout<<-1<<endl;
    }
    return 0;
}

G - The Galactic Olympics

题意:k种物品放进n个空位里,每个空位只能放一个物品,每种物品可以放到多个空位里,问每种物品都有放置且最后n个空位都放满的方案数有多少种

思路:考点是第二类斯特林数。
在k大于n的时候是没有方案数的。
其他情况下。我们考虑,如果是对每个人去选要去的空位,会产生很多重复的地方。
因为这里n是大于等于k的,所以考虑把n个物品分配给k个人。我们先把n个物品分成k组,然后再分步相乘,乘上k组的排列即可。
比如k=2, n=4, 我们可以先将4分成2两组,有
1 3
2 2
的搭配,方案数数是(C{_4 ^3})+(C{_4 ^2})/2 = 7,再乘上两组间调换位置,全排列(A{_2}^2)等于14。
但是当分组变得更多的时候呢,这个时候方案数就不好一下子确定了,所以引进第二类斯特林数。
采用递推式
(Y[i][j] = Y[i-1][j-1] + j*Y[i-1][j])即可求得,其中Y[i][j]代表对i个数分成j组。记得最后乘上k的全排列。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll Y[1005][1005];


int main()
{
    freopen("galactic.in","r", stdin);
    int kase;
    cin>>kase;
    while(kase--)
    {
        ll n = read(), m = read();
        if(m > n) cout<<0<<endl;
        else
        {
            Y[0][0] = 1;
            rep(i,1,n) rep(j,1,m) Y[i][j] = (Y[i-1][j-1] + (j*Y[i-1][j]))%mod;
            ll ans = 1;
            rep(i,1,m) ans = (ans%mod*i%mod)%mod;
            ans = (ans%mod * Y[n][m]%mod)%mod;
            cout<<ans<<endl;
        }
    }
    return 0;
}


H - Commandos

dp模板题,当前状态可以由题中三个状态转移过来。从楼层从上到下dp一遍,最后在底层找最大即可。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll dp[20][20][20];
ll f[20][20][20];

int main()
{
    freopen("commandos.in", "r", stdin);
    int kase;
    cin>>kase;
    while(kase--)
    {
        mem(f,0); mem(dp,0);
        ll n = read();
        rep(i,1,n)
        {
            ll x = read(), y = read(), z = read();
            f[x][y][z] = read();
        }
        per(x,10,1) rep(y,1,10) rep(z,1,10) dp[x][y][z] = max(max(dp[x+1][y][z], dp[x][y-1][z]), dp[x][y][z-1]) + f[x][y][z];
        ll ans = 0;
        rep(y,1,10) rep(z,1,10) ans = max(dp[1][y][z], ans);
        cout<<ans<<endl;
    }

    return 0;
}

原文地址:https://www.cnblogs.com/Bgwithcode/p/13835990.html