A-大吉大利








代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include <vector>
#include<map>
#include<set>
#include<utility>
#define    scanf1(a) scanf("%d",&a)
#define    scanf2(a,b) scanf("%d%d",&a,&b)
#define mes(a,b)    memset(a,b,sizeof a)
#define  js  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
ll a[100005],b[100005],n,temp,cnt;
ll ans=0;
ll qpow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans*=a;
        a*=a;
        b>>=1;
    }
    return ans;
}
int main() {
    js;
    cin>>n;
    for(int i=0;i<n;++i) {
        cin>>a[i];
        temp=a[i],cnt=0;
        while(temp) {
            if(temp&1)    b[cnt]++;
            ++cnt;
            temp>>=1;
        }
    }
    for(int i=0;i<n;++i) {
        cnt=0;
        while(a[i]) {
            if(a[i]&1) ans+=b[cnt]*qpow(2,cnt);
            ++cnt;
            a[i]>>=1;
        }
    }
    cout<<ans<<endl;
}

B-三角形周长和

数据保证三点补共线,我们先任取2点形成一条边,那么剩下n-2个点,都可以和这两点形成一个三角形,也就是说每个边都会出现n-2次,直接边输入边计算就可以了,代码如下(%其实挺慢的):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include <vector>
#include<map>
#include<set>
#include<utility>
#define    scanf1(a) scanf("%d",&a)
#define    scanf2(a,b) scanf("%d%d",&a,&b)
#define mes(a,b)    memset(a,b,sizeof a)
#define  js  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
struct node{
    ll x,y;
}q[1005];
ll ans=0,cnt,n;
int main() {
    js;
    cin>>n;
    cnt=n-2;
    for(int i=1;i<=n;++i) {
        cin>>q[i].x>>q[i].y;
        for(int j=1;j<i;++j) {
            ans+=(abs(q[i].x-q[j].x)+abs(q[i].y-q[j].y))*cnt;
            while(ans>=998244353)    ans-=998244353;
        }
    }
    while(ans>=998244353)    ans-=998244353;
    cout<<ans<<endl;
}

C-操作集锦

dp[i][j]表示考虑前i个字符形成的长度为j的子序列个数。
状态转移方程为:dp[i][j]=dp[i-1][j]+dp[i-1][j-1];
当有相同的字符出现时还要去掉重复的部分,而这一部分被包括在dp[i-1][j-1];
用pre[i]记录s[i]最近一次出现的位置,
因为+dp[i-1][j-1]表示前i-1个字符组成的长度为j-1的子序列后面加上s[i],
故多出来的就是dp[pre[s[i]-'a']-1][j-1];
代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include <vector>
#include<map>
#include<set>
#include<utility>
#define    scanf1(a) scanf("%d",&a)
#define    scanf2(a,b) scanf("%d%d",&a,&b)
#define mes(a,b)    memset(a,b,sizeof a)
#define  js  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int mod = 1e9 + 7;
ll dp[1005][1005];
int n,k,pre[1005];
char s[1005];
int main() {
    js;
    cin>>n>>k;
    cin>>(s+1);
    dp[0][0]=1;
    for(int i=1;i<=n;++i) {
        dp[i][0]=1;
        for(int j=1;j<=i;++j) {
            dp[i][j]=dp[i-1][j]+dp[i-1][j-1];
            if(pre[s[i]-'a'])    dp[i][j]-=dp[pre[s[i]-'a']-1][j-1];
            dp[i][j]%=mod;
        }
        pre[s[i]-'a']=i;
    }
    ll ans=dp[n][k];
    if(ans<0)    ans+=mod;
    cout<<ans<<endl;
}

D-斩杀线计算大师

最短路bcj目前看不懂,不会写。
ax+by=c,有解的充要条件是gcd(a,b)|c,即a,b的最大公约数能被c整除。
对ai+bx+cy=k;可以遍历i,转化为二元bx+cy=k-ai,k-ai>=0,如果不满足gcd(b,c)|(k-ai)就跳过。
由ax+by=gcd(a,b)得到解x,则bx+cy=k-ai的一个特解x=x*(k-ai)/gcd(b,c);
其中x模c不同余的解共有d个:


x的最小非负解为:
i和x都有了,y就简单了,最后判断x,y是否都是非负数就行了:

#include<bits/stdc++.h>
using namespace std;
#define  js  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ll long long
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 a,b,c,k,x,y,temp,sum;
    js;
    cin>>a>>b>>c>>k;
    temp=gcd(b,c);
    for(ll i=0;a*i<=k;++i) {
        if((k-a*i)%temp!=0)    continue;
        sum=(k-a*i)/temp;
        exgcd(b,c,x,y);
        x*=sum;
        x=(x%(c/temp)+(c/temp))%(c/temp);
        y=(k-a*i-b*x)/c;
        if(x<0||y<0)    continue;
        cout<<i<<" "<<x<<" "<<y<<endl;
        break;
    }
    return 0;
}