A
让求一个和式的值,按照和式内容模拟要两个for,n^2复杂度会TLE,所以显然是不可取的
那么因为是位运算& 所以我们考虑去按位算贡献,对于每一位,我们会进行
k*(k-1)次计算 也就是排列数A(k,2) 那么该位对答案的贡献就是就是(1<<i) * k * (k-1) 其中k为该位上为1的个数
所以存下来每个数的每一位1的个数 (因为只有1&1才能对答案有贡献)
然后遍历每一位计算贡献的值即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define me(a,x) memset(a,x,sizeof a) #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define all(x) (x).begin(), (x).end() #define pb(a) push_back(a) #define paii pair<int,int> #define pali pair<ll,int> #define pail pair<int,ll> #define pall pair<ll,ll> #define x first #define y second ll a[100005]; ll q[65]; int main() { int n;cin>>n; ll sum=0; for(int i=1;i<=n;i++) { cin>>a[i],sum+=a[i]; for(int j=0;j<64;j++){ if((a[i]>>j)&1) q[j]++; } } for(int i=0;i<64;i++){ // cout<<i<<" "<<q[i]<<endl; sum+=q[i]*(q[i]-1)*(1ll<<i); } cout<<sum<<endl; return 0; }
B
让计算三角形的周长,这里的周长指的是曼哈顿距离,因为三角形每次是选择三个点
那么也就是每两个点之间的距离会被选中n-2次
n只有1e3 所有直接两个for暴力计算两个点之间的曼哈顿距离乘上n-2即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define me(a,x) memset(a,x,sizeof a) #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define all(x) (x).begin(), (x).end() #define pb(a) push_back(a) #define paii pair<int,int> #define pali pair<ll,int> #define pail pair<int,ll> #define pall pair<ll,ll> #define x first #define y second pall a[1005]; ll mod=998244353; int main() { int n;cin>>n; for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y; ll sum=0; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ sum=(sum+((n-2)*(abs(a[i].x-a[j].x)+abs(a[i].y-a[j].y))%mod)%mod)%mod; } } cout<<sum<<endl; return 0; }
C
是个dp
考虑一个二维dpdp[i][j]表示以i结尾的长度位j的合法的方案数
因为我们要去除那些重复的 所以拉一个二维数组 q[i][j]表示当前位置为i的下一个字符为j的位置
这样可以不会多算了 也就是满足题中的要求
那么转移方程容易得到 dp[id][j+1]=dp[id][j+1]+dp[i][j] 其中id为i的下一个字符的位置
初始状态就是dp[0][0]=1
复杂度n * n * 26
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define me(a,x) memset(a,x,sizeof a) #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define all(x) (x).begin(), (x).end() #define pb(a) push_back(a) #define paii pair<int,int> #define pali pair<ll,int> #define pail pair<int,ll> #define pall pair<ll,ll> #define x first #define y second ll x,y; ll mod=1e9+7; ll dp[1005][1005]; ll q[1005][130]={0}; char s[1005]; int main() { ll n,kk; cin>>n>>kk; cin>>s+1; dp[0][0]=1; for(int i=0;i<n;i++){ for(int j=i+1;j<=n;j++){ if(q[i][s[j]]==0) q[i][s[j]]=j; } } for(int i=0;i<n;i++){ for(int j=0;j<=i;j++){ if(dp[i][j]!=0){ for(int k='a';k<='z';k++){ int id=q[i][k]; if(id!=0) dp[id][j+1]=(dp[id][j+1]+dp[i][j])%mod; } } } } ll ans=0; for(int i=kk;i<=n;i++) ans=(ans+dp[i][kk])%mod; cout<<ans<<endl; return 0; }
D
第一眼看到 就是exgcd跑不了
因为是个不定方程嘛
然后题意已经说了保证有解 而要求的是ax+by+cz=k的一组解(x,y,z)
exgcd是解决二元不定方程的,所以我们去枚举一下a的值,然后得到了by+cz=k-ax
我们去计算(k-ax)%gcd(b,c) 是不是为0 为0就说明了这个不定方程有解
然后跑一遍exgcd 让y变为最小正整数解 在计算z是否≥0即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define me(a,x) memset(a,x,sizeof a) #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define all(x) (x).begin(), (x).end() #define pb(a) push_back(a) #define paii pair<int,int> #define pali pair<ll,int> #define pail pair<int,ll> #define pall pair<ll,ll> #define x first #define y second ll a,b,c,k; ll x,y; ll mod=1e9+7; void exgcd(ll a,ll b,ll &x,ll &y) { if(b==0) { x=1; y=0; return; } ll x1,y1; exgcd(b,a%b,x1,y1); x=y1; y=x1-(a/b)*y1; } int main() { cin>>a>>b>>c>>k; for(int i=0;i<=1000000;i++){ ll q=k-1ll*i*a,gcd=__gcd(b,c); if(q%gcd==0){ exgcd(b,c,x,y); x=q/gcd*x; x=(x%(c/gcd)+c/gcd)%(c/gcd); y=(q-x*b)/c; if(y>=0){ cout<<i<<" "<<x<<" "<<y<<endl; break; } } } return 0; }