k倍區間
阿新 • • 發佈:2018-02-21
取余 %d sum efi mem bsp urn pla hide
用前綴和來求區間和,然後用一個二重循環窮舉,但是因為問題規模為100000
,所以超時(28分)
超時代碼:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <string.h> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #includeView Code<map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 100010 #define MAX 0x06FFFFFF #define V vector<int> #define ll long long using namespace std; ll sum[LEN]; int main(){// freopen("D:/CbWorkspace/blue_bridge/k倍區間.txt","r",stdin); int i,j,n,k,ans=0; I("%d%d",&n,&k); FF(i,n){ I("%d",&j); sum[i+1]=sum[i]+j; } for(i=1;i<=n;i++){ for(j=i;j<=n;j++){ int t=(sum[j]-sum[i-1]); if((sum[j]-sum[i-1])%k==0) ans++; } } printf("%d\n",ans); return 0; }
觀看了大佬的AC代碼,終於明白怎麽回事了。一句話, 計算前綴和然後取余k, 如果前i項和取余k與前j項和取余k後相同,那麽i到j這個區間和為k的倍數
註意ans,cnt,sum都要開 long long
AC代碼:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <string.h> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 100010 #define MAX 0x06FFFFFF #define V vector<int> #define ll long long using namespace std; ll sum[LEN]; ll cnt[LEN]; int A(int n,int m){ int a=1; while(m){ a*=n--; m--; } return a; } int C(int n,int m){ int c=A(n,m); while(m){ c/=m--; } return c; } int main(){ // freopen("D:/CbWorkspace/blue_bridge/k倍區間.txt","r",stdin); int i,j,n,k; ll ans=0; I("%d%d",&n,&k); FF(i,n){ I("%d",&j); sum[i+1]=sum[i]+j; } cnt[0]=1; F(i,1,n+1){ cnt[sum[i]%k]++; } FF(i,k){ if(cnt[i]) ans+=cnt[i]*(cnt[i]-1)/2; //C(n,2) } printf("%lld",ans); return 0; }
k倍區間