Niu Keプラクティス60(A、B、C(サブシーケンスDP)、D(拡張ユークリッド)E(ヒューリスティックマージ))

タイトルリンク

グレートラッキー

練習:ビット単位の演算を実行し、各ビットの数を1として数えます。数は奇数で、ビットは回答に寄与し、次に進みます。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=2e5+10;
ll a[N],n;
int main()
{
	cin>>n;
	rep(i,1,n) scanf("%lld",&a[i]);
	ll pre=0,num=0;
	ll ans=0;
	for(ll j=0;j<=60;++j){
        num=0;
        rep(i,1,n)
        {
            if((a[i]>>j)&1ll)num++;
        }

        ll s=num*num;
        s+=pre;
        if(s%2) ans+=(1ll<<j);

        pre=s/2;
	}
	cout<<ans;
}

 

B三角形の円周

方法:2つのポイントを列挙し、他のポイントからこれらの2つのポイントまでのマンハッタン距離を求めます。xとyは別々に並べ替えられ、O(1)はプレフィックスの合計を使用して取得できます。

 

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e3+10;
const ll mod=998244353;
ll x[N],y[N],n,pre[N],ans;
void cal(ll x[])
{
//    rep(i,1,n)
//    {
//        printf("i:%d x:%lld\n",i,x[i]);
//    }
    //sort(x+1,x+1+n);
    rep(i,1,n) pre[i]=(pre[i-1]+x[i]);


    rep(i,1,n)
    for(int j=i+1;j<=n-1;++j){
	    ans+=(pre[n]-pre[j]-(n-j)*x[i])%mod;
	    ans+=mod;
	    ans+=(pre[n]-pre[j]-(n-j)*x[j])%mod;
	    ans%=mod;
	    ans+=(n-j)*(x[j]-x[i]);
	    ans%=mod;
	}
}
int main()
{
	cin>>n;
	rep(i,1,n)
	{
	    scanf("%lld%lld",&x[i],&y[i]);
	    x[i]+=1e9+10,y[i]+=1e9+10;
	}
	sort(x+1,x+1+n);
	sort(y+1,y+1+n);
	cal(x);
	cal(y);
	cout<<ans<<endl;
}

 

 

Cオペレーションのハイライト

本質的に異なるサブシーケンスを見つける

アイデア:最初のi桁のサブシーケンスの数をf(i)とします。

           1. i番目の桁が最初のi桁に現れていない場合、i-1桁の元のサブシーケンスは、最初のi桁のサブシーケンスでもあり、合計f(i-1)、およびi-1桁の元のサブシーケンスの後に[i]も続きます。これも新しいサブシーケンスであり、合計f(i-1)です。最後の桁だけでも新しいサブシーケンスを形成できます。 1つなので、現時点ではf(i)= f(i)+ f(i)+1です。

           2. i番目の曲番号が前のi番号に現れた場合、f(i)= f(i)+ f(i)-f(a [i]最後の位置-1)。このとき、a [i]が1つの場合が計算されているので、+ 1はなく、[i] −1の最後に[i]を追加した場合も計算されている。 、1回差し引かれます。


 

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e3+10;
const ll mod=1e9+7;
char s[N];
int n,m;
ll dp[N][N],vis[30],last[N];
void add(ll &x,ll y)
{
    x=(x+y)%mod;
}
int get(char c)
{
    return c-'a';
}
int main()
{
	cin>>n>>m>>s+1;

	if(m==0){
        printf("1");
        return 0;
	}

	//rep(i,1,n) dp[1][s[i]-'a'

	for(int i=1;i<=n;++i){
        int id=get(s[i]);
	    for(int j=1;j<=m&&j<=n;++j){
           add(dp[i][j],dp[i-1][j]);
	    }
	    for(int j=1;j<=m&&j<=n;++j){
           add(dp[i][j+1],dp[i-1][j]);
	    }

	    if(last[id]==0) add(dp[i][1],1);
	    else{
            for(int j=2;j<=m&&j<=n;++j){
                dp[i][j]=(dp[i][j]-dp[last[id]-1][j-1]+mod)%mod;
            }
	    }
        last[id]=i;

	}
	//ll ans=0;
    //rep(i,1,n) printf("i:%d %lld\n",i,dp[i][2]);
	cout<<dp[n][m]<<endl;
}
/*
4 2
abab

5 2
abcc

5 3
abccc

*/

D-スラッシャーマスター

実践:参照元:ポータル

exgcd分かりませんか?

exgcdリファレンスブログを学ぶ:ポータル

わかりやすい

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=998244353;
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){x=1;y=0;
        return a;
    }
    ll r=exgcd(b,a%b,x,y);
    ll temp=x;
    x=y;
    y=temp-(a/b)*y;
    return r;
}
ll gcd(ll a,ll b){
    if(a%b==0)return b;
    return gcd(b,a%b);
}

int main(){
    ll t,i,j,n,k,m=0,a,b,c;
    cin>>a>>b>>c>>k;
    ll g=gcd(b,c);
    for(i=0;i<k/a;i++){
        if((k-a*i)%g!=0)continue;

        ll x,y;
        ll cc=exgcd(b,c,x,y);

        t=(k-a*i)/cc;//乘上t才是目前 b,c的其中一个解

        ll x1=x*t,y1=y*t,c1=c/g;

        //printf("x1:%lld y1:%lld\n",x1,y1);
        x1=(x1%c1+c1)%c1;//最小正整数解,类似于取模 模数为c1
        y1=(k-a*i-b*x1)/c;

        if(x1<0||y1<0)continue;
        cout<<i<<" "<<x1<<" "<<y1;
        break;
    }
}

 

E競争相手

方法:ヒューリスティックスを組み合わせる、mp [u] [x]はxのノード深度のノードの重みの合計、num [u] [x]はxのノード深度のノード数です。

ここでは、uとvのサイズを判断してからスワップする手順がありません。これはデータの水です。

ゲーム終了後、オフセットを表す配列dep [i]を追加し、iノードが上がったときにオフセットを記録して、実際のヒューリスティックマージを実現します。2番目のコード

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=2e5+10;
int n,k,a[N];
vector<int>G[N];
map<int,ll>mp[N],num[N];
ll ans[N];
void dfs(int u,int f)
{
    for(int v:G[u])
    {
        if(v==f) continue;
        dfs(v,u);
        ll val=0;
        for(auto x:mp[v]){
            int d=k-x.first-1;
            if(d<=0) continue;
            if(mp[u][d]==0) continue;


            val+=num[u][d]*mp[v][x.first];
            val+=num[v][x.first]*mp[u][d];

        }
        for(auto x:mp[v]){
            mp[u][x.first+1]+=x.second;
            num[u][x.first+1]+=num[v][x.first];
        }
        ans[u]+=val;
    }
    num[u][0]++;
    mp[u][0]+=a[u];
}
int main()
{
	cin>>n>>k;
	rep(i,1,n) scanf("%d",&a[i]);
	rep(i,2,n)
	{
	    int u,v;
	    scanf("%d%d",&u,&v);
	    G[u].push_back(v);
	    G[v].push_back(u);
	}
	dfs(1,1);
	rep(i,1,n)
	printf("%lld ",ans[i]);
}

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=2e5+10;
int n,k,a[N];
vector<int>G[N];
map<int,ll>mp[N],num[N];
ll ans[N],dep[N];
void dfs(int u,int f)
{
    for(int v:G[u])
    {
        if(v==f) continue;
        dfs(v,u);
        ll val=0;
        dep[v]++;
      
        if(mp[u].size()<mp[v].size()) 
        {
        	swap(mp[u],mp[v]);
			swap(num[u],num[v]); 
			swap(dep[u],dep[v]);
		}

        for(auto x:mp[v]){
            int d=k-(x.first+dep[v])-dep[u];
            if(mp[u][d]==0) continue;

            val+=num[u][d]*mp[v][x.first];
            val+=num[v][x.first]*mp[u][d];

        }
        for(auto x:mp[v]){
            mp[u][x.first+dep[v]-dep[u]]+=x.second;
            num[u][x.first+dep[v]-dep[u]]+=num[v][x.first];
        }
        ans[u]+=val;
    }
    num[u][-dep[u]]++;
    mp[u][-dep[u]]+=a[u];
}
int main()
{
	cin>>n>>k;
	rep(i,1,n) scanf("%d",&a[i]);
	rep(i,2,n)
	{
	    int u,v;
	    scanf("%d%d",&u,&v);
	    G[u].push_back(v);
	    G[v].push_back(u);
	}
	dfs(1,1);
	rep(i,1,n)
	printf("%lld ",ans[i]);
}

 

元の記事519件を公開 賞賛された69件 50,000件以上の表示

おすすめ

転載: blog.csdn.net/qq_41286356/article/details/105152311