目录
一.1.22(洛谷)
1.P8761
该题就是一个大小写的转换。
#include<stdio.h>
#include<string.h>
int main(void)
{
int k;
char a[101];
scanf("%s", a);
k=strlen(a);
for(int i=0;i<k;i++)
{
if(a[i]>='a'&&a[i]<='z')
{
a[i]-=32;
}
}
puts(a);
return 0;
}
2.P8195
该题就是检测一个连续的字符串
#include<stdio.h>
#include<string.h>
int main(void)
{
int k, c=0;
char a[400001];
scanf("%s", a);
k=strlen(a);
for(int i=0;i<=k-8;i++)
{
if(a[i]=='c'&&a[i+1]=='h'&&a[i+2]=='u'&&a[i+3]=='a'&&a[i+4]=='n'&&a[i+5]=='z'&&a[i+6]=='h'&&a[i+7]=='i')
c++;
}
printf("%d", c);
return 0;
}
3.P8651
一开始我的想法是去考虑它年月日、月日年、日月年三种排列分别的可能情况。但后面发现在输出时,输出的结果有不满足条件的。
后面改变想法:去考虑19600101到20591231中满足条件的情况。
#include<stdio.h>
int nian(int y);
int yue(int y,int m);
int ri[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main(void)
{
int a, b, c, y, m, d, k;
scanf("%d/%d/%d", &a, &b, &c);
for(int i=19600101;i<=20591231;i++)
{
y=i/10000;
m=i/100%100;
d=i%100;
k=0;
if(m<=0||m>=13)
continue;
if(d<=0||d>yue(y,m))
continue;
if(y%100==a&&m==b&&d==c)
k=1;
if(m==a&&d==b&&y%100==c)
k=1;
if(d==a&&m==b&&y%100==c)
k=1;
if(k==1)
printf("%02d-%02d-%02d\n",y,m,d);
}
return 0;
}
int nian(int y)
{
if(y%400==0||(y%4==0&&y%100!=0))
return 1;
return 0;
}
int yue(int y,int m)
{
if(m==02&&nian(y)==1)
return 29;
else
return ri[m];
}
4.P9240
该题我的一开始的想法就是考虑o%x==0和o%x!=0两种情况,然后在去判断o/x的值做最大值,取所有最大值的最小值,还有判断不小于o/(x+1)的值做最小值,取所以最小值的最大值。以此来判断出所以数组的共同最大值和最小值。
#include<stdio.h>
#include<math.h>
#include<algorithm>
int main(void)
{
int n, o, x, max=1000000000, min=-1000000000, t;
scanf("%d", &n);
for(int i=0;i<n;i++)
{
scanf("%d%d", &o, &x);
if(o%x==0)
{
if(o/x<max)
max=o/x;
t=ceil((o*1.0)/(x+1));
if(t>min)
min=t;
}
if(o%x!=0)
{
t=o/x;
if(t<max)
max=t;
t=ceil((o*1.0)/(x+1));
if(t>min)
min=t;
}
}
printf("%d %d", min, max);
return 0;
}
5.P8627
该题我使用了函数,通过反复调用函数,去计算实际能得到的饮料数。函数的功能是去计算当前的n(饮料瓶)能去换多少个新n(饮料瓶)。
#include<stdio.h>
int a(int n);
int s=0;
int main(void)
{
int n;
scanf("%d", &n);
s+=n;
for(;n!=0;)
{
s+=n/3;
n=a(n);
}
printf("%d", s);
return 0;
}
int a(int n)
{
int k;
if(n%3==0)
{
n=n/3;
}
else
{
k=n%3;
n=n/3+k;
}
if(n<3)
return 0;
else
return n;
}
6.P8647**
该题刚开始我没做出来。
后面网上看了一下其他人的做法,先计算每一个边长下可以切分的巧克力数量,再与孩子数量做比较即可,那么每次选择的边长可以用二分查找,而每一块巧克力可以切分的目标大小巧克力数量就是(n/r)* (m/r) n、m分别为当前巧克力的长度,宽度。
#include<iostream>
using namespace std;
typedef long long LL;
const int N = 100010;
int a[N],b[N];
int n,k;
bool check(int mid){
LL ans=0;
for(int i=0;i<n;i++)ans+=(a[i]/mid)*(b[i]/mid);
if(ans>=k)return true;
else return false;
}
int main(){
cin>>n>>k;
int ans=0;
for(int i=0;i<n;i++){
scanf("%d%d",&a[i],&b[i]);
ans=max(a[i],max(ans,b[i]));
}
int l=0,r=2*ans;
while(l<r){
int mid=(l+r)>>1;
if(check(mid))l=mid+1;
else r=mid;
}
printf("%d",l-1);
return 0;
}
7.P8637**
这道题我一开始也是没做出来。
后面的想法是这样的:先判断该元素是否在属于它的位置上,如果不在,就找到它然后交换,记录交换的次数。
#include<stdio.h>
int main()
{
int a[10010],t,s=0,n,i,j,k;
scanf("%d",&n);
for(i=1; i<=n; i++)
scanf("%d",&a[i]);
for(i=1; i<=n; i++)
if(a[i]!=i)
{
for(j=1; j<=n; j++)
if(a[j]==i)
{
t=a[i];
a[i]=i;
a[j]=t;
break;
}
s++;
}
printf("%d\n",s);
return 0;
}
8.P8625**(树状dp)
该题考察的知识点是树状dp,不过我当时还不会。。。
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 100010;
int n;
int w[N];
ll f[N];
ll res;
vector<int> g[N];
void dfs(int u, int fa){
for (int i = 0; i < g[u].size(); i ++ ){
int son = g[u][i];
if (son != fa){
dfs(son, u);
f[u] += max(0ll, f[son]);
}
}
res = max(res, f[u]);
}
int main(){
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> w[i], f[i] = w[i];
for (int i = 0; i < n - 1; i ++ ){
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, -1);
cout << res << endl;
return 0;
}
9.P8638**(最长公共子序列(LCS))
这道题是一个求最长公共子序列(LCS)的题目。而求LCS我们可以使用动态规划(dp)的办法。
状态设置:
f[i][j]表示的是序列Si = {x1,x2,x3,...,xi}与序列Sj = {y1,y2,y3,...,yj}的最长公共子序列的长度。
状态转移方程:
当i=0,j=0时,f [ i ][ j ] = 0;
当xi = yi时,f [ i ][ j ] = 1 + f [ i - 1 ][ j - 1 ];
当xi != yi时,f [ i ][ j ] = max( f [ i - 1 ][ j ] , f [ i ][ j - 1 ] );
最长子序列即为f [ n ][ m ](n为s1的长度,m为s2的长度)。
#include <iostream>
using namespace std;
int n;
int f[1001][1001];
int LCS(string s1,string s2)
{
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= n;j++)
{
if(s1[i-1] == s2[j-1])
{
f[i][j] = 1 + f[i-1][j-1];
}
else
{
f[i][j] = max(f[i-1][j],f[i][j-1]);
}
}
}
return f[n][n];
}
int main()
{
string s1;
while(cin >> s1)
{
n = s1.length();
string s2 = s1;
for(int i = 0;i < n;i++)
{
s2[n-i-1] = s1[i];
}
int ans = n-LCS(s1,s2);
cout << ans << endl;
}
return 0;
}
10.P8774**
额,这道题,额,弄了很久,也没弄明白,看了网上很多解法,才搞明白了一点,先附的代码,继续研究吧。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
ll qpow(ll num, ll pow, ll p){
ll ans=1;
while(pow){
if(pow&1) ans=ans*num;
num*=num;
ans%=p;
num%=p;
pow >>= 1;
}
return ans;
}
int main(){
ll x,y,n;
ll p=998244353;
cin>>n;
ll E[n];
E[0]=0;
ll i;
for(i=1;i<=n;i++){
cin>>x;
cin>>y;
E[i]=((E[i-1]+1)%p*(y%p))%p;
E[i]*=qpow(y-x,p-2,p);
E[i]%=p;
}
cout<<E[n];
return 0;
}
二.1.24(洛谷)
1.P8506
该题我的想法是从开头开始检测,先排除掉开头不为'#'与' '的情况,当检测到'#'时,判断其后一位是否为' ',是的话继续判断其后续有无非' '的字符。
注意:该段代码需要在C语言、C++98、C++11的编译环境下才能编译成功。
#include<stdio.h>
#include<string.h>
int main(void)
{
int n, c=0, m, k;
char a[11][101];
scanf("%d", &n);
getchar();
for(int i=0;i<n;i++)
{
gets(a[i]);
m=strlen(a[i]);
for(int j=0;j<m-1;j++)
{
k=0;
if(a[i][j]!='#'&&a[i][j]!=' ')
{
break;
}
if(a[i][j]=='#')
{
if(a[i][j+1]==' ')
{
for(int o=j+1;o<m;o++)
{
if(a[i][o]!=' ')
{
c++;
k=1;
break;
}
}
}
else
{
break;
}
}
if(k==1)
{
break;
}
}
}
printf("%d", c);
return 0;
}
2.P8507
该题的思路就是每人有1门科目没通过,则每人科目不通过的概率为1/a,所以b人每门科目的不通过的人为(floor)(b/a)。不通过率即为(floor)(b/a)/b。
#include<stdio.h>
#include<math.h>
int main(void)
{
double a, b;
scanf("%lf%lf", &a, &b);
printf("%.16lf", (floor)(b/a)/b);
return 0;
}
3.P8508**
这道题我一开始的思路是枚举天数。对于每一天,判断如果做下一个任务,是否满足题目条件。重复这个过程,可以做的任务则做,否则直接睡大觉。
(但超时了。。。)
优化了一下:倒序插入任务,再算出前面需要睡几天大觉。
#include<bits/stdc++.h>
using namespace std;
long long n,x,p,q,i=1,sum,t,w;
int main(){
cin>>n>>x>>p>>q;
while(n--){
cin>>w;
if((x-t-w+sum)*q>=i*p*x&&x-t>w){
t+=w;
}
else{
sum+=x-t;
i++;
long long l=ceil((q*(sum+x-w)-p*i*x)*1.0/(x*p-x*q));
if(l>0){
sum+=x*l;
i+=l;
}
t=w;
}
}
cout<<i;
return 0;
}
4.B3691**
这道题我的思路是先所有奇数都不是优秀的拆分,因为它含有2^0,而偶数从它所含有的最大2次方进行输出,直至结果为0时返回0。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
long long cf[32];
cf[2]=2;cf[1]=1;
cin>>n;
if(n%2==1){
cout<<"-1"<<endl;
return 0;
}
for(int i=3;i<=27;i++)
cf[i]=2*cf[i-1];
int n1=n;
for(int i=27;i>=2;i--){
if(n==0)
return 0;
if(cf[i]<=n1){
n1=n1-cf[i];
cout<<cf[i]<<" ";
}
}
}
5.P1048
小背包问题
#include<stdio.h>
#include<algorithm>
int main(void)
{
int m,t;
int a[105],b[105];
int c[105][1005];
scanf("%d%d", &t, &m);
for(int i=1;i<=m;i++)
{
scanf("%d%d", &a[i], &b[i]);
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=t;j++)
{
c[i][j]=c[i-1][j];
if(j>=a[i])
{
c[i][j]=std::max(c[i-1][j],c[i-1][j-a[i]]+b[i]);
}
}
}
printf("%d", c[m][t]);
return 0;
}
6.P7060
额,额,嘿嘿,因为其实这道题数据并不多,思路也不复杂,所以我直接把每一种情况都列了一种可能出来。
#include<stdio.h>
int main(void)
{
int n;
scanf("%d", &n);
if(n<8||n>26)
{
printf("Impossible");
}
else
{
if(n==8)
printf("11:11");
if(n==9)
printf("11:17");
if(n==10)
printf("11:14");
if(n==11)
printf("11:13");
if(n==12)
printf("01:11");
if(n==13)
printf("01:17");
if(n==14)
printf("01:14");
if(n==15)
printf("01:12");
if(n==16)
printf("01:01");
if(n==17)
printf("07:01");
if(n==18)
printf("04:01");
if(n==19)
printf("02:01");
if(n==20)
printf("00:01");
if(n==21)
printf("00:07");
if(n==22)
printf("00:04");
if(n==23)
printf("00:02");
if(n==24)
printf("00:09");
if(n==25)
printf("08:00");
if(n==26)
printf("08:08");
}
return 0;
}
7.P8889**
8.P6225**
这道题我没有什么思路。
然后我在网课看题解时看到了这一种思路:
只有当奇偶性相同的时候才有答案,而答案就是l,l+2,......,r。
但是这里需要注意修改操作
对于异或树状数组的修改 ,我们仍然可以使用上面那个性质。
const int N = 2e5+10;
int t1[N],t2[N],a[N];
int n,m;
int lowbit(int x){
return x & (-x);
}
void add(int *C,int x,int k){
for(int i = x;i <= n ; i += lowbit(i))
C[i]^=k;
}
int query(int *C,int x){
int sum = 0;
for(int i = x; i ; i-=lowbit(i))
sum^=C[i];
return sum;
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
if(i&1)
add(t1,i,a[i]);
else
add(t2,i,a[i]);
}
for(int i=1;i<=m;i++){
int op,x,y;
cin>>op>>x>>y;
if(op == 1){
if(x%2 !=0)
{
add(t1,x,a[x]^y);
a[x] = y;
}
else{
add(t2,x,a[x]^y);
a[x] = y;
}
}else{
if(((x&1)^(y&1)))
cout<<0<<endl;
else
{
if(x%2 !=0 ){
int l = query(t1,y);
int r = query(t1,x-1);
int ans = l^r;
cout<<ans<<endl;
}else{
int l = query(t2,y);
int r = query(t2,x-1);
int ans = l^r;
cout<<ans<<endl;
}
}
}
}
}
9.U360489**
10.P1352**
三.1.26(洛谷)
1.P6056
该题好像没什么需要注意的点,吧?
就是有一个循环去一天一天的计算当天恢复的和感染的人数,并为当天结束时的易感人数、感染人数、恢复人数重新赋值。
有一个点就是当天的新增感染人数大于易感人数时,新增感染人数按易感人数算。
#include<stdio.h>
#include<math.h>
int main(void)
{
int S, I, R=0, n, x, z;
double b, y;
scanf("%d%d%d", &S, &I, &n);
scanf("%lf%lf", &b, &y);
for(int i=0;i<n;i++)
{
x=ceil(b*S*I);
z=ceil(y*I);
if(x>S)
{
x=S;
}
R=R+z;
S=S-x;
I=I-z+x;
}
printf("%d %d %d", S, I, R);
return 0;
}
2.P1765
我的想法就是把每种情况都列出来。
#include<stdio.h>
#include<string.h>
int main(void)
{
int k, c=0;
char a[201];
gets(a);
k=strlen(a);
for(int i=0;i<k;i++)
{
if(a[i]==' ')
{
c+=1;
}
if(a[i]=='a'||a[i]=='d'||a[i]=='g'||a[i]=='j'||a[i]=='m'||a[i]=='p'||a[i]=='t'||a[i]=='w')
{
c+=1;
}
if(a[i]=='b'||a[i]=='e'||a[i]=='h'||a[i]=='k'||a[i]=='n'||a[i]=='q'||a[i]=='u'||a[i]=='x')
{
c+=2;
}
if(a[i]=='c'||a[i]=='f'||a[i]=='i'||a[i]=='l'||a[i]=='o'||a[i]=='r'||a[i]=='v'||a[i]=='y')
{
c+=3;
}
if(a[i]=='s'||a[i]=='z')
{
c+=4;
}
}
printf("%d", c);
return 0;
}
3.P4305
我一开始的想法是先读取一个数组,然后对数组中的每个元素进行判断,如果该元素已经出现过了,则把它赋值为-1,否则不变,最后在输出时进行判断,如果当前元素为-1,则不输出。(结果超时了,呜呜┭┮﹏┭┮)
然后我就投机取巧用了map,,,嘿嘿。
#include<iostream>
#include<unordered_map>
using namespace std;
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
unordered_map<int, bool> mp;
for (int i = 1; i <= n; i++) {
int a;
cin >> a;
if (!mp.count(a)) {
cout << a << ' ';
mp[a] = true;
}
}
cout << endl;
}
return 0;
}
4.P1145
看到这道题,一开始我思路是懵的,然后发现这道题就是一个条件判断,即当报数遇到好人时,结束,把报的数+1,重新开始判断,如此循环,直至首个满足条件的值出现。
#include<stdio.h>
int main(void)
{
int k, t, p;
scanf("%d", &k);
t=k+1;
for(;;)
{
p=0;
for(int i=0;i<k;i++)
{
p=(p+t-1)%(2*k-i);
if(p<k)
break;
if(i==k-1)
{
printf("%d", t);
goto end;
}
}
t++;
}
end:
return 0;
}
5.P8742**
这道题可以去遍历所有可能的重量,若某重量w可以被表示,则分为一下几种情况:
1.w+m也可以被表示(将w和m都放到砝码盘)
2.若w > m ,那么 w-m 也可以被表示(将m放到物品栏,w放到砝码盘)
3.若w < m,那么m-w 也可以被表示 (将m放到砝码盘,w放到物品盘)
#include<iostream>
#include<queue>
#include<math.h>
using namespace std;
const int N = 100005;
int n;
bool f[N];
int ans;
int a;
queue<int>q;
int main()
{
cin>>n;
f[0]=true;
for(int i=1;i<=n;++i)
{
cin>>a;
for(int j=0;j<N;++j)
{
if(f[j])
{
q.push(abs(j-a));
if(j+a<N) q.push(j+a);
}
}
while(!q.empty())
{
f[q.front()]=true;
q.pop();
}
}
for(int i=1;i<N;++i) if(f[i]) ans++;
cout<<ans<<endl;
return 0;
}
6.P6473**
这道题可以用贪心,每一次取大的,然后用二分判断每一次加在一起够不够。
#include<bits/stdc++.h>
#define maxn 200001
using namespace std;
int n,L,v,m,t;
long long a[maxn],sum[maxn];
bool cmp(const int &x,const int &y){
return x>y;
}
int main(){
scanf("%d%d%d",&n,&L,&v);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
scanf("%d",&m);
while(m--){
scanf("%d",&t);
int l=-1,r=n+1,mid;
while(l+1<r){
mid=(l+r)>>1;
if(sum[mid]+L<=(long long)t*v)l=mid;
else r=mid;
}
if(r>n)printf("-1\n");
else printf("%d\n",r);
}
return 0;
}
7.P8808
这道题我一开始的想法就是生成一个斐波那契数列的数组,与读取的数组进行一一比较,用c去记录数据不同的个数。
(结果又超时了,呜呜┭┮﹏┭┮)
然后我注意到题目给出的数据中数组的元素值的范围为1到10的6次方。而斐波那契数列的第31个元素的值就大于了10的6次方,故只需要判断前30项就行,如果n大于30,则大于30的部分必定是不同的。
(结果还是不对,o.O)
然后我又认真看了一下题目,原来是斐波那契数组,其中一个条件是a0=a1,而不是a0=a1=1。所以可能出现数据是斐波那契数列的倍数,所以我又用了循环去找最小的c。
#include<stdio.h>
#include<algorithm>
int ahunshu(int n);
int a[30];
int main(void)
{
int n, c, k=0, minc=100001;
int b[30];
scanf("%d", &n);
if(n>30)
{
k=n-30;
n=30;
}
if(n<=30)
{
for(int i=1;i<=n;i++)
{
a[i-1]=ahunshu(i);
}
/*
for(int i=0;i<n;i++)
{
printf("%d", a[i]);
}
printf("\n");
*/
for(int i=0;i<n;i++)
{
scanf("%d", &b[i]);
}
/*
for(int i=0;i<n;i++)
{
printf("%d", a[i]);
}
printf("\n");
for(int i=0;i<n;i++)
{
scanf("%d", &b[i]);
if(b[i]!=a[i]&&b[i]%a[i]!=0)
{
c++;
}
}
*/
for(int i=1;i<=1e6;i++)
{
c=0;
for(int j=0;j<n;j++)
{
c+=int(b[j]!=i*a[j]);
/*
if(b[j]!=i*a[j])
{
c++;
}
*/
}
minc=std::min(c, minc);
}
printf("%d", k+minc);
}
return 0;
}
int ahunshu(int n)
{
if(n==1||n==2)
{
return 1;
}
else
{
return a[n-2]+a[n-3];
}
}
8.[ABC325E]**
这道题我基本没什么思路,看了挺久网上的题解,才稍微明白了一点点。
我看到一个思路是:
建一个分层图跑 dijkstra 就可以了。第一个图G1全部以坐车需要的时间为边权,第二个图 G 2 G2G2 全部以坐高铁需要的时间为边权。因为坐车可以转坐高铁,所以 G 1 G1G1 中每个点向 G 2 G2G2 中对应的点连一条边权为 0 00 的边就好了。
#include<bits/stdc++.h>
using namespace std;
int n,A,B,C;
int a[1010][1010];
struct node{
int v,w;
bool operator<(const node &b)const{
return w>b.w;
}
};
vector<node> G[200010];
int dis[200010];
void Dijkstra(){
dis[1]=0;
priority_queue<node> q;
q.push({1,0});
while(!q.empty()){
int u=q.top().v;
q.pop();
for(auto x:G[u]){
int v=x.v,w=x.w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push({v,dis[v]});
}
}
}
}
signed main(){
memset(dis,0x3f,sizeof(dis));
cin>>n>>A>>B>>C;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>a[i][j];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
G[i].push_back({i+n,0});
G[i].push_back({j,A*a[i][j]});
G[i+n].push_back({j+n,B*a[i][j]+C});
}
}
Dijkstra();
cout<<min(dis[n],dis[n+n])<<endl;
return 0;
}
9.P8786**
使用三维数组dp[i][j][k]表示在遇到第i个店和第j个花,以及遇到k个花的情况下的方案数。
#include<bits/stdc++.h>
using namespace std;
int mod = 1e9 + 7;
long long dp[105][105][105] = {0};
int main()
{
int n,m;
cin >> n >> m;
dp[0][0][2] = 1;
dp[0][1][1] = 1;
dp[0][2][0] = 1;
for (int i = 0; i <= 7; i++)
{
dp[i][0][int(pow(2, i + 1))] = 1;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
for (int k = 0; k <= m; k++)
{
if (k % 2 == 0)
dp[i][j][k] = (dp[i - 1][j][k / 2] + dp[i][j - 1][k + 1]) % mod;
else
dp[i][j][k] = dp[i][j - 1][k + 1];
}
}
}
cout << dp[n][m-1][1] << endl;
return 0;
}
10.P1685**
这道题又要用拓扑排序进行统计(我还搞不太明白。。。)不过它直接是加法原理和乘法原理上去就行了。(稍微简单了一丢丢吧,没搞那么复杂)。
#include <cstdio>
#include <queue>
#define ll long long
using namespace std;
const int N=10010;
const int M=50010;
const ll mod=10000;
int n,m,s,t,in[N];
int head[N],to[M],Next[M],cnt;
ll t0,edge[M],Cnt[N],len[N];
void add(int u,int v,ll w)
{
to[++cnt]=v;Next[cnt]=head[u];edge[cnt]=w;head[u]=cnt;
}
void init()
{
scanf("%d%d%d%d%lld",&n,&m,&s,&t,&t0);
int u,v;ll w;
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&u,&v,&w);
if(u!=v)
{
add(u,v,w);
in[v]++;
}
}
}
queue <int > q;
void work()
{
q.push(s);
Cnt[s]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=Next[i])
{
int v=to[i];ll w=edge[i];
in[v]--;
Cnt[v]=(Cnt[u]+Cnt[v])%mod;
len[v]=((len[v]+len[u])%mod+w*Cnt[u]%mod)%mod;
if(!in[v])
q.push(v);
}
}
ll ans=((Cnt[t]-1)*t0%mod+len[t])%mod;
printf("%lld\n",ans);
}
int main()
{
init();
work();
return 0;
}
四.反思总结
本周训练的内容,涉及的算法较多,暴露出我的问题如:
1.对一些算法的掌握程度还不够好,导致做题卡顿。需要加强的还有二分,贪心。
2.掌握的算法知识还不够多,碰到如树状数组的题目没有思路写。需要补充的是树状数组,位运算,拓扑排序,最短路,树状DP,动态规划DP,哈希。
对于问题1:重新复习一遍这些算法,自己实现代码模板复现,要求下次碰到这类算法时能迅速想出解题步骤,再把这周涉及这些算法的题重新做过去,直到不卡顿为止。对于问题2:在CSDN和B站上找了相关视频和文章学习这些算法,清楚了算法实现的原理和步骤,再回头把这些算法的题目做过去,做到能脱离题解写出AC代码,空闲时手写一遍算法思路步骤。
总而言之,本周的训练让我感觉在算法竞赛的道路上又前进了一步,希望自己能坚持下去,以饱满的热情,完成冬训,提高自己的水平,在后面的算法竞赛里拿到好成绩。