A 签到题
链接:http://222.204.56.169/contest/20/problem/A
题意:
找规律签到
题解:
按照给的代码多组输入一下,找到规律,写出来即可
代码:
#include<iostream> #include<cstdio> using namespace std; int main() { int n; scanf("%d",&n); if(n&1)printf("1");else printf("-1"); return 0; }
B 阶乘
链接:http://222.204.56.169/contest/19/problem/B
题意:
找一个数后面有几个0
题解:
其实就是因子中有多少个5,因为5存在一个5前面就有一个2,就是找因子中存在5的个数,例如:n=31中,有因子-> 5 10 15 20 25 30 (31/5=6就是代表这几个数的个数) 然后每五个这样连续的数就会出现5*5这样的数,所以(得到的6/5=1)再加进去直到n=0为止
代码:
#include<bits/stdc++.h> using namespace std; int main() { long long n,num; cin>>n; num=0; while(n!=0) { num=num+n/5; n=n/5; } cout<<num<<endl; return 0; }
C 合并滑稽
链接:http://222.204.56.169/contest/19/problem/C
题意:
把一串数并在一起,每一次需要消耗对应的数相加的体力。使得体力消耗最小。
题解:
每一次的合并,之前的数都要算一遍,也就是说小的数线合并所消耗的体力会最小,只要每次都用一个sort排序就好了。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int a[100005]; int main() { int n; scanf("%d",&n); memset(a,0,sizeof(a)); for(int i=0;i<n;i++) {scanf("%d",&a[i]);} int ans=0; for(int i=0;i<n-1;i++) { sort(a,a+n); a[i+1]+=a[i]; ans+=a[i+1]; a[i]=0; } printf("%d",ans); return 0; }
D ff爱组合数
链接:http://222.204.56.169/contest/19/problem/D
题意:
就是求C_n^m的组合数%p
题解:
可以利用递推(具体的实践在算法笔记P186)
代码:
#include<iostream> #include<cstdio> using namespace std; const int p=1e9+9; int res[20009][2009]={0}; int n,m; void calC(int x) { for(int i=0;i<x;i++) { res[i][0]=res[i][i]=1; } for(int i=2;i<=x;i++) { for(int j=0;j<=i/2;j++) { res[i][j]=(res[i-1][j]+res[i-1][j-1])%p; res[i][i-j]=res[i][j]; } } } int main() { int T; scanf("%d",&T); int n,m; calC(2000); while(T--) { scanf("%d%d",&n,&m); printf("%d\n",res[n][m]); } return 0; }
E 猜猜在哪里
链接:http://222.204.56.169/contest/19/problem/E
题意:
题解:
注意:我不会呀~~呜呜呜呜
代码:
#include <bits/stdc++.h> using namespace std; const int N = 200000 + 10; typedef long long LL; const LL MOD = 998244353; LL mpow(LL a, LL x) { if (x == 0) return 1; LL t = mpow(a, x>>1); if (x % 2 == 0) return t * t % MOD; return t * t % MOD * a % MOD; } struct Nod { LL k, b, s; Nod operator + (const Nod & o) const { Nod ans; ans.k = 1; ans.b = 0; ans.s = (s + o.s) % MOD; return ans; } } nod[N << 2]; void build(int l,int r,int rt){ if(l==r){ nod[rt].k=1,nod[rt].b=0;nod[rt].s=0; return; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); nod[rt] = nod[rt<<1] + nod[rt<<1|1]; } void upd(int rt, LL k, LL b) { nod[rt].k = nod[rt].k * k % MOD; nod[rt].b = (nod[rt].b * k + b) % MOD; nod[rt].s = (nod[rt].s * k + b) % MOD; } void pushdown(int rt) { upd(rt<<1, nod[rt].k, nod[rt].b); upd(rt<<1|1, nod[rt].k, nod[rt].b); nod[rt].k = 1, nod[rt].b = 0; } void update(int l,int r,int rt,int L,int R,LL k,LL b){ if (L<=l&&r<=R) { upd(rt, k, b); return; } pushdown(rt); int mid=(l+r)>>1; if(L<=mid) update(l,mid,rt<<1,L,R,k,b); if(R >mid) update(mid+1,r,rt<<1|1,L,R,k,b); nod[rt]=nod[rt<<1]+nod[rt<<1|1]; } int query(int l,int r,int rt,int pos){ if(l==r){ return nod[rt].s; } pushdown(rt); int mid=(l+r)>>1; if(pos<=mid) return query(l,mid,rt<<1,pos); return query(mid+1,r,rt<<1|1,pos); } void modify(int l,int r,int rt,int pos,int x){ if(l==r){ nod[rt].s=x; return; } pushdown(rt); int mid=(l+r)>>1; if(pos<=mid) modify(l,mid,rt<<1,pos,x); else modify(mid+1,r,rt<<1|1,pos,x); nod[rt] = nod[rt<<1] + nod[rt<<1|1]; } int t;LL n, m, k; bool flag[N]; int item1[N], item2[N]; LL inv(LL x){ return mpow(x%MOD, MOD-2); } const bool CHK = 0; LL A[N]; void ran_swap() { // tot = 1, myval = x // N: (n-2)/n * x // Y: 2/(n(n-1)) * (1 - x) // [(n-2)/n - 2/(n(n-1))] * x + 2/(n(n-1)) LL k = (n-2)*inv(n) - 2*inv(n*(n-1)); k = (k % MOD + MOD) % MOD; LL b = 2*inv(n*(n-1)); b = (b % MOD + MOD) % MOD; update(1,n,1,1,n,k,b); if (CHK) { for (int i = 1; i <= n; i ++) { LL ans = (n-2) * inv(n) % MOD * A[i] % MOD; ans += 2 * inv(n) % MOD * ( (1 - A[i] + MOD) % MOD * inv(n-1) % MOD ) % MOD; ans %= MOD; A[i] = ans; } } } void _swap(int x, int y) { int v1 = query(1,n,1,x); int v2 = query(1,n,1,y); modify(1,n,1,x,v2); modify(1,n,1,y,v1); if (CHK) swap(A[x], A[y]); } void chk() { for (int i = 1; i <= n; i ++) { printf("# %lld %d\n", A[i], query(1,n,1,i)); assert(A[i] == query(1,n,1,i)); } } int main() { scanf("%d", &t); while (t --) { scanf("%lld%lld%lld", &n, &m, &k); build(1, n, 1); modify(1, n, 1, 1, 1); for (int i = 1; i <= n; i ++) A[i] = 0; A[1] = 1; for (int i = 1; i <= m; i ++) { flag[i] = 0; } for (int i = 1; i <= k; i ++) { int op,x,y; scanf("%d%d%d",&op,&x,&y); flag[op] = 1; item1[op] = x, item2[op] = y; } for (int i = 1; i <= m; i ++) { if (flag[i]) { _swap(item1[i], item2[i]); } else { ran_swap(); } } if (CHK) { chk(); } for (int i = 1; i <= n; i ++) { printf("%d%c", query(1,n,1,i),i==n?'\n':' '); } LL s = 0; for (int i = 1; i <= n; i ++) { s += query(1,n,1,i); s %= MOD; } assert(s == 1); //printf("sum = %lld\n", s); } }
F 约数的个数
链接:http://222.204.56.169/contest/19/problem/F
题意:
f(n)为n约数的个数,求F(n)=1f(1)+2f(2)+、、、+n*f(n)
题解:神奇的筛法
for(int i=1;i<=n;i++) for(int j=i;j<=n;j+=i) F[j]++;
注意:自行理解,其实表示的就是i为约数的时候,每一个n以内的数都会进行一个计算作为i的倍数对应数字j的约数个数+1,这样其实就是算出来了n以内的所有不同数字对应的约数个数。然后叠加一下就可以啦~
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll f[1000006]; ll F[1000006]; void iserv(ll n) { for(ll i=1;i<=n;i++) for(ll j=i;j<=n;j+=i) f[j]++; } int main() { ll x; scanf("%lld",&x); memset(f,0,sizeof(f)); iserv(x); F[1]=1*f[1]; for(ll i=2;i<=x;i++) { F[i]=F[i-1]+i*f[i]; } printf("%lld",F[x]); return 0; }