c语言刷题app河南理工大学,【题解】河南理工大学新生挑战赛

A、Dong Zhi

直接输出即可。

#include

using namespace std;

int main()

{

printf("Let's eat dumplings");

return 0;

}

B、The flower

利用

equation?tex=map&preview=true储存长为

equation?tex=k&preview=true的字符串,暴力计算即可。

#include

using namespace std;

int main(){

string s;

int k;

cin>>s>>k;

unordered_map mmp;

set st;

int n=(int)s.length();

for(int i=k-1;i

string now=s.substr(i-(k-1),k);

mmp[now]++;

st.insert(now);

}

set ans;

for(auto v:st){

if(mmp[v]>2){

ans.insert(v);

}

}

cout<

for(auto v:ans) cout<

return 0;

}

C、Xor Path

equation?tex=DFS&preview=true计算从根节点到每个节点的异或和,同时计算倍增。然后利用倍增可以实现

equation?tex=O(log_n)&preview=true的查询。

#include

using namespace std;

const int N = 1e6+100;

vector G[N];

int pre[N],a[N],par[N];

long long bit[30];

int f[N][30];

int depth[N];

void init(){

bit[0]=1;

for(int i=1;i<=29;i++) bit[i]=(bit[i-1]<<1);

}

void dfs(int u,int par){

depth[u]=depth[par]+1;

f[u][0]=par;

for(int i=1;bit[i]<=depth[u];i++) f[u][i]=f[f[u][i-1]][i-1];

for(int v:G[u]){

if(v!=par) dfs(v,u);

}

}

int lca(int x,int y){

if(depth[x]

for(int i=29;i>=0;i--){

if(depth[x]-depth[y]>=bit[i]){

x=f[x][i];

}

}

if(x==y) return x;

for(int i=29;i>=0;i--){

if(depth[x]>=(1<

x=f[x][i];

y=f[y][i];

}

}

return f[x][0];

}

void DFS1(int u,int fa){

par[u]=fa;

pre[u]=pre[fa]^a[u];

for(int v:G[u]){

if(v==fa) continue;

DFS1(v,u);

}

}

int main(){

int n,u,v,q;

cin>>n;

init();

for(int i=1;i<=n;i++) cin>>a[i];

for(int i=0;i<=n;i++) G[i].clear();

for(int i=1;i<=n-1;i++){

cin>>u>>v;

G[u].push_back(v);

G[v].push_back(u);

}

dfs(1,0);

DFS1(1,0);

int x,y;

cin>>q;

while(q--){

cin>>x>>y;

int c=lca(x,y);

int f=par[c];

cout<

}

return 0;

}

D、LaunchPad

开两个数组分别记录当前行或列是否有操作,再开一个二维数组计算每个灯在操作后的亮灭情况(用来调整行和列所带来的一次操作而不是两次操作)。

#include

using namespace std;

#define ll long long

const int maxn=1000+10;

int a[maxn],b[maxn];

int c[maxn][maxn];

int main()

{

int n,m,q;

scanf("%d %d",&n,&m);

scanf("%d",&q);

while(q--){

int u,v;

scanf("%d %d",&u,&v);

c[u][v]^=1;

a[u]^=1;

b[v]^=1;

}

int ans=0;

for(int i=1;i<=n;i++){

for(int j=1;j<=m;j++){

ans+=a[i]^b[j]^c[i][j];

}

}

printf("%d\n",ans);

return 0;

}

E、Morse code

长度为

equation?tex=2&preview=true

equation?tex=4&preview=true种情况已经全部出现过,长度为

equation?tex=3&preview=true

equation?tex=8&preview=true种情况也已经出现过,因此我们一定能够利用长度为

equation?tex=2&preview=true

equation?tex=3&preview=true的字母去填充,因此答案就是

equation?tex=len%2F2&preview=true

此处给出

equation?tex=dp&preview=true做法,以供学习。

#include

using namespace std;

const int maxn=1e6+10;

mapmp;

string code[100];

char s[maxn];

int dp[maxn];

void init(){

code[1]=".-"; code[2]="-..."; code[3]="-.-."; code[4]="-..";

code[5]="..-."; code[6]="--."; code[7]="....";

code[8]=".."; code[9]=".---"; code[10]="-.-"; code[11]=".-..";

code[12]="--"; code[13]="-."; code[14]="---"; code[15]=".--.";

code[16]="--.-";code[17]=".-."; code[18]="...";

code[19]="..-"; code[20]="...-"; code[21]=".--";code[22]="-..-";

code[23]="-.--"; code[24]="--..";

for(int i=1;i<=24;i++){

int num=0;

for(int j=0;j

mp[num]++;

}

}

int cal(int a,int b){

int num=0;

for(int i=a;i<=b;i++) num=num*100+s[i];

return mp[num]?1:0;

}

void solve(){

scanf("%s",s);

int n=strlen(s);

for(int i=0;i

dp[i]=0;

for(int j=1;j<=4;j++){

int y=i-j;

dp[i]=max(dp[i],dp[i-j]+cal(i-j+1,i));

}

}

printf("%d\n",dp[n-1]);

}

int main()

{

init();

int t;

scanf("%d",&t);

while(t--){

solve();

}

return 0;

}

F、Puzzle

原签到题。

#include

using namespace std;

#define ll long long

#define pii pair

const ll maxn=1000000+10;

const ll INF=0x3f3f3f3f3f3f3f3f;

const ll mod=1e9+7;

int a[100];

void init(){

a[0]=1;

a[1]=0;

a[2]=0;

a[3]=0;

a[4]=1;

a[5]=0;

a[6]=1;

a[7]=0;

a[8]=2;

a[9]=1;

}

int main()

{

init();

int t;

scanf("%d",&t);

while(t--){

ll x;

scanf("%lld",&x);

if(x==0) printf("1\n");

else{

int num=0;

while(x){

num+=a[x%10];

x/=10;

}

printf("%d\n",num);

}

}

return 0;

}

G、Triangle tower

尖向上的小三角形能够组成一个杨辉三角,向下的又能够组成一个杨辉三角,因此分情况计算即可。

#include

using namespace std;

#define ll long long

const ll mod=1e9+7;

const int maxn=100000+10;

ll fac[maxn];

void init(){

fac[0]=1;

for(int i=1;i<=maxn;i++) fac[i]=fac[i-1]*i%mod;

}

ll qp(ll a,ll b){

ll res=1;

while(b){

if(b&1) res=res*a%mod;

a=a*a%mod;

b>>=1;

}

return res;

}

ll c(int n,int m){

return fac[n]*qp(fac[m],mod-2)%mod*qp(fac[n-m],mod-2)%mod;

}

ll solve(int n,int m){

n--;

if(m%2==0) n--;

m=(m-1)/2;

printf("%lld\n",c(n,m));

}

int main()

{

int t,n,m;

scanf("%d",&t);

init();

while(t--){

scanf("%d %d",&n,&m);

solve(n,m);

}

return 0;

}

H、Kingdom of Mathematics

应该是整个比赛里面最难的一个题?

Part1

$

equation?tex=%0A2f(n)%2Bf(n%2B1)%3Df(n%2B2)-2n%2B1%20%5C%5C%5C%20%0Af(n%2B2)-f(n%2B1)%3D2f(n)%2B2n-1%20%5C%5C%5C%20%0Af(n%2B1)-f(n)%3D2f(n-1)%2B2(n-1)-1%20%5C%5C%5C%20%0Af(n)-f(n-1)%3D2f(n-2)%2B2(n-2)-1%20%5C%5C%5C%20%0A...%20%5C%5C%5C%20%0Af(3)-f(2)%3D2f(1)%2B2-1%20%5C%5C%5C%20%0Af(2)-f(1)%3D2f(0)%2B0-1%20%5C%5C%5C%0A&preview=true

equation?tex=%0A%E5%B7%A6%E8%BE%B9%E7%9B%B8%E5%8A%A0%E4%B8%8E%E5%8F%B3%E8%BE%B9%E7%9B%B8%E5%8A%A0%E5%8D%B3%E5%8F%AF%E5%BE%97%EF%BC%9A%0A&preview=true

equation?tex=%0Af(n%2B2)-f(1)%3D2%5Csum_%7Bi%3D0%7D%5E%7Bn%7D(f(i)%2Bi)-n-1%20%5C%5C%5C%20%0Af(n%2B2)%3D2%5Csum_%7Bi%3D0%7D%5E%7Bn%7D(f(i)%2Bi)-n%20%5C%5C%5C%20%0Af(n%2B2)%2B(n%2B2)%3D2%5Csum_%7Bi%3D0%7D%5E%7Bi%3Dn%7D(f(i)%2Bi)%2B2%0A&preview=true

equation?tex=%0A%E8%AE%BE&preview=trueg(x)=f(x)+x

equation?tex=%20%2C%E5%88%99%EF%BC%9A%0A&preview=true

equation?tex=%0Ag(n%2B2)%3D2%5Csum_%7Bi%3D0%7D%5E%7Bi%3Dn%7D(g(i))%2B2%20%5C%5C%5C%20%0Ag(n%2B1)%3D2%5Csum_%7Bi%3D0%7D%5E%7Bi%3Dn-1%7D(g(i))%2B2%20%5C%5C%5C%20%0Ag(n%2B2)-g(n%2B1)%3D2g(n)%20%5C%5C%5C%20%0Ag(n%2B2)%3Dg(n%2B1)%2B2g(n)%20%5C%5C%5C%20%0Ag(n%2B1)%3Dg(n)%2B2g(n-1)%20%5C%5C%5C%20%0A...%20%5C%5C%5C%20%0Ag(3)%3Dg(1)%2B2g(0)%20%5C%5C%5C%20%0A%5Cbecause%20g(0)%3Df(0)%2B0%3D1%2Cg(1)%3Df(1)%2B1%3D2%20%5C%5C%5C%20%0A%5Ctherefore%20g(2)%3D4%20%5C%5C%5C%20%0A%5Ctherefore%20g(n)%3D2%5En%0A&preview=true

equation?tex=%0A%E6%89%80%E4%BB%A5%E5%8F%AF%E8%AE%A1%E7%AE%97%E5%87%BA%EF%BC%9A%0A&preview=true

equation?tex=%0Af(x)%3Dg(x)-x%20%5C%5C%5C%20%0A%3D2%5Ex-x%0A&preview=true$

Part2

可以发现,

equation?tex=f(x)&preview=true的二进制表示位数为

equation?tex=x&preview=true位,而且在

equation?tex=x&preview=true足够大时,可以发现高位数几乎全为

equation?tex=1&preview=true。我们将

equation?tex=f(x)&preview=true每两项进行异或

equation?tex=(f(1)%5Cbigoplus%20f(2)%2Cf(3)%5Cbigoplus%20f(4)%20...)&preview=true,可以发现

equation?tex=f(2n-1)%5Cbigoplus%20f(2n)%3D2%5E%7B2n-1%7D%2B1&preview=true ,因此前偶数项我们就可以用类似的方法计算出结果

equation?tex=((11)_2%5Cbigoplus(1001)_2%5Cbigoplus%20(100001)%5Cbigoplus...)&preview=true ,结果为各项

equation?tex=2%5Ek&preview=true部分相加,最后一位判断总共有多少对即可。

对于奇数

equation?tex=n&preview=true,我们已知前

equation?tex=n-1&preview=true位的值

equation?tex=101010101010...&preview=true,我们将其分为两部分,低位部分位

equation?tex=n&preview=true影响到的部分(即与高位全一部分的分界线),高位部分为全一部分。然后分开计算即可。

#include

using namespace std;

#define ll long long

const int maxn=1000000+10;

const ll mod=1e9+7;

ll T,n;

ll qp(ll a,ll b){

ll res=1;

while(b){

if(b&1) res=res*a%mod;

a=a*a%mod;

b>>=1;

}

return res;

}

//等比数列前x项之和 第一项为1

ll judge(ll x){

ll sum=(qp(4,x)-1+mod)%mod;

return 2*sum*qp(3,mod-2)%mod;

}

//二进制位数

ll bits(ll x){

ll sum=0;

while(x){

sum++;

x>>=1;

}

return sum;

}

ll revise(ll x,ll step){

ll pos=1;

stackst;

for(int i=1;i<=step;i++){

if(i%2==0) st.push(1-(x&1));

else st.push(x&1);

x>>=1;

}

ll sum=0;

while(!st.empty()){

sum=sum*2+st.top();

st.pop();

}

return sum;

}

int main()

{

scanf("%lld",&T);

while(T--){

ll res;

scanf("%lld",&n);

if(n&1){

ll vis=bits(n);

//高位没被影响到的的值

res=judge((n-vis)/2);

if((n-vis)&1) res=(res*2+1)%mod;

res=res*qp(2,vis)%mod;

//低位被异或的值

res=(res+revise((1ll<

//最后一位加or减

if((n/2)&1){

if(n&1) res=(res-1+mod)%mod;

else res=(res+1)%mod;

}

}

else{

res=judge(n/2);

if((n/2)&1) res=(res+1)%mod;

}

printf("%lld\n",res);

}

return 0;

}

I、HPU's birthday

暴力计算每个

equation?tex=0&preview=true的贡献即可,假如某个

equation?tex=0&preview=true前面有

equation?tex=n&preview=true

equation?tex=1&preview=true,那么它的贡献即为

equation?tex=a*(a-1)%2F2&preview=true

#include

using namespace std;

#define ll long long

const ll mod=1e9+7;

int q[100];

int main()

{

int t;

scanf("%d",&t);

while(t--){

int n;

scanf("%d",&n);

int num=0;

ll ans=0;

ll x=n;

while(x){

q[num++]=x&1;

x>>=1;

}

x=0;

for(int i=0;i

for(int j=num-1;j>=0;j--){

if(q[j]) x++;

else ans=(ans+x*(x-1)/2)%mod;

}

}

printf("%lld\n",ans);

}

return 0;

}

以下为

equation?tex=n%3D10%5E%7B18%7D&preview=true的解法:

#include

using namespace std;

#define ll long long

const ll mod=1e9+7;

int q[100];

ll qp(ll a,ll b){

ll res=1;

while(b){

if(b&1) res=res*a%mod;

a=a*a%mod;

b>>=1;

}

return res;

}

ll cal(ll x,ll n,ll a){

ll ans=0;

ans=n*x*x%mod;

ans=(ans+(n-1)%mod*n%mod*x%mod*a%mod);

ans=(ans+(n-1)%mod*n%mod*(2*n-1)%mod*qp(2,mod-2)%mod*a%mod*a%mod);

ans=(ans-n%mod*x%mod+mod)%mod;

ans=(ans-(n-1)%mod*n%mod*qp(2,mod-2)%mod*a%mod+mod)%mod;

return ans;

}

int main()

{

ll inv2=qp(2,mod-2);

ll t;

scanf("%lld",&t);

while(t--){

ll n;

scanf("%lld",&n);

ll num=0,ans=0,x=n;

ll one=0;

while(x){

if(x&1) one++;

q[num++]=x&1;

x>>=1;

}

x=0;

for(int i=num-1;i>=0;i--){

if(q[i]) x++;

else ans=(ans+cal(x,n,one));

}

printf("%lld\n",ans*inv2%mod);

}

return 0;

}

J、Max Sum

我们首先记录前缀和数组

equation?tex=pre%5B%5D&preview=true和后缀和数组

equation?tex=nxt%5B%5D&preview=true,然后对其建两棵线段树。

对于第

equation?tex=i&preview=true个位置,我们计算区间

equation?tex=%5Bi-k-1%2Ci-1%5D&preview=true的最小前缀和和

equation?tex=%5Bi%2B1%2Ci%2Bk%2B1%5D&preview=true的最小后缀和,数组总和减去这两部分的值即为第

equation?tex=i&preview=true个位置的最大值。由于数据范围的原因,还要特别处理一下边界条件。

#include

using namespace std;

#define ll long long

const int maxn=1000000+10;

const int INF=0x3f3f3f3f;

int a[maxn];

ll pre[maxn],nxt[maxn];

int k[maxn];

int N;

struct Tree{

ll x[maxn];

void init(int x){

N=1;

while(N<=x*2) N*=2;

}

void update(int k,int q){

k+=N-1;

x[k]=q;

while(k){

k=(k-1)/2;

x[k]=min(x[k*2+1],x[k*2+2]);

}

}

ll query(int a,int b,int l,int r,int k){

if(r

if(a<=l && r<=b) return x[k];

else{

ll vl=query(a,b,l,(l+r)/2,k*2+1);

ll vr=query(a,b,(l+r)/2+1,r,k*2+2);

return min(vl,vr);

}

}

}tp,tn;

int main()

{

int n;

scanf("%d",&n);

for(int i=1;i<=n;i++) scanf("%d",&k[i]);

tp.init(n);

ll sum=0;

for(int i=1;i<=n;i++){

scanf("%d",&a[i]);

sum+=a[i];

tp.update(i,sum);

}

sum=0;

for(int i=n;i>=1;i--){

sum+=a[i];

tn.update(i,sum);

}

ll ans=0;

for(int i=1;i<=n;i++){

ans+=sum;

ans-=tp.query(max(i-k[i]-1,0),max(i-1,0),0,N-1,0);

ans-=tn.query(min(i+1,n+1),min(i+k[i]+1,n+1),0,N-1,0);

}

printf("%lld\n",ans);

return 0;

}

K、Restore Expressions

要使中的贡献最小,首先把除了第一项以外的值全部置为

equation?tex=1&preview=true,仅考虑第一项的值即可,假设表达式的值为

equation?tex=0&preview=true,计算出两个式子第一项值为

equation?tex=a%2Cb&preview=true,那么我们就进行如下操作:若其中一项不为正数,则两个数均加上一个值使得两个数均为正数。这样可以使得两个式子值相同且贡献尽可能的小。

#include

using namespace std;

const int maxn=2000000+10;

char s[maxn],t[maxn];

void solve(){

int n;

scanf("%d",&n);

scanf("%s %s",s,t);

int a=0,b=0;

for(int i=0;i

if(s[i]=='-') a++;

else a--;

if(t[i]=='-') b++;

else b--;

}

int prea,preb;

prea=a+max(1-min(a,b),0);

preb=b+max(1-min(a,b),0);

printf("%d %d\n",0,prea+preb+n*2);

printf("%d",prea);

for(int i=1;i<=n;i++) printf(" %d",1);

printf("\n");

printf("%d",preb);

for(int i=1;i<=n;i++) printf(" %d",1);

printf("\n");

}

int main()

{

solve();

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值